diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index fa259e05255a..910e58ecb71a 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -660,7 +660,7 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode, dsi->format = format; bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); - if (bpp < 0) { + if (bpp <= 0) { DRM_DEV_ERROR(dsi->dev, "failed to get bpp for pixel format %d\n", dsi->format); diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c index 55612fe0e285..968fd14c1bc2 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -628,6 +628,9 @@ static void dw_mipi_dsi2_phy_ratio_cfg(struct dw_mipi_dsi2 *dsi2) pixel_clk = mode->crtc_clock * MSEC_PER_SEC; ipi_clk = pixel_clk / 4; + if (!sys_clk || !ipi_clk) + return; + tmp = DIV_ROUND_CLOSEST_ULL(phy_hsclk << 16, ipi_clk); regmap_write(dsi2->regmap, DSI2_PHY_IPI_RATIO_MAN_CFG, PHY_IPI_RATIO(tmp)); diff --git a/drivers/gpu/drm/rockchip/rk628/rk628_dsi.c b/drivers/gpu/drm/rockchip/rk628/rk628_dsi.c index aa67ff0ce021..766f156efb98 100644 --- a/drivers/gpu/drm/rockchip/rk628/rk628_dsi.c +++ b/drivers/gpu/drm/rockchip/rk628/rk628_dsi.c @@ -637,6 +637,9 @@ static int rk628_dsi_read_from_fifo(struct rk628_dsi *dsi, u32 val; int ret; + if (!vrefresh) + return -EINVAL; + ret = regmap_read_poll_timeout(dsi->regmap, dsi->reg_base + DSI_CMD_PKT_STATUS, val, !(val & GEN_RD_CMD_BUSY), diff --git a/drivers/media/i2c/dw9800w.c b/drivers/media/i2c/dw9800w.c index 1d11568ed7ed..21fe6a40775b 100644 --- a/drivers/media/i2c/dw9800w.c +++ b/drivers/media/i2c/dw9800w.c @@ -44,6 +44,7 @@ enum mode_e { /* dw9800w device structure */ struct dw9800w_device { struct v4l2_ctrl_handler ctrls_vcm; + struct v4l2_ctrl *focus; struct i2c_client *client; struct v4l2_subdev sd; struct v4l2_device vdev; @@ -52,13 +53,14 @@ struct dw9800w_device { struct gpio_desc *power_gpio; unsigned short current_related_pos; unsigned short current_lens_pos; + unsigned int max_current; unsigned int start_current; unsigned int rated_current; - unsigned int step; unsigned int step_mode; unsigned int vcm_movefull_t; unsigned int t_src; unsigned int t_div; + unsigned int max_logicalpos; struct __kernel_old_timeval start_move_tv; struct __kernel_old_timeval end_move_tv; @@ -67,7 +69,6 @@ struct dw9800w_device { u32 module_index; const char *module_facing; struct rk_cam_vcm_cfg vcm_cfg; - int max_ma; struct mutex lock; }; @@ -217,22 +218,25 @@ static int dw9800w_get_pos(struct dw9800w_device *dev_vcm, unsigned int *cur_pos) { struct i2c_client *client = dev_vcm->client; + unsigned int dac, position, range; int ret; - unsigned int abs_step; - ret = dw9800w_read_reg(client, 0x03, 2, &abs_step); + range = dev_vcm->rated_current - dev_vcm->start_current; + ret = dw9800w_read_reg(client, 0x03, 2, &dac); if (ret != 0) goto err; - if (abs_step <= dev_vcm->start_current) - abs_step = VCMDRV_MAX_LOG; - else if ((abs_step > dev_vcm->start_current) && - (abs_step <= dev_vcm->rated_current)) - abs_step = (dev_vcm->rated_current - abs_step) / dev_vcm->step; - else - abs_step = 0; + if (dac <= dev_vcm->start_current) { + position = dev_vcm->max_logicalpos; + } else if ((dac > dev_vcm->start_current) && + (dac <= dev_vcm->rated_current)) { + position = (dac - dev_vcm->start_current) * dev_vcm->max_logicalpos / range; + position = dev_vcm->max_logicalpos - position; + } else { + position = 0; + } - *cur_pos = abs_step; + *cur_pos = position; dev_dbg(&client->dev, "%s: get position %d\n", __func__, *cur_pos); return 0; @@ -245,16 +249,18 @@ err: static int dw9800w_set_pos(struct dw9800w_device *dev_vcm, unsigned int dest_pos) { - int ret; - unsigned int position = 0; - struct i2c_client *client = dev_vcm->client; + struct i2c_client *client = v4l2_get_subdevdata(&dev_vcm->sd); + unsigned int position; + unsigned int range; u32 is_busy, i; + int ret; - if (dest_pos >= VCMDRV_MAX_LOG) + range = dev_vcm->rated_current - dev_vcm->start_current; + if (dest_pos >= dev_vcm->max_logicalpos) position = dev_vcm->start_current; else position = dev_vcm->start_current + - (dev_vcm->step * (VCMDRV_MAX_LOG - dest_pos)); + (range * (dev_vcm->max_logicalpos - dest_pos) / dev_vcm->max_logicalpos); if (position > DW9800W_MAX_REG) position = DW9800W_MAX_REG; @@ -304,10 +310,10 @@ static int dw9800w_set_ctrl(struct v4l2_ctrl *ctrl) if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) { - if (dest_pos > VCMDRV_MAX_LOG) { + if (dest_pos > dev_vcm->max_logicalpos) { dev_info(&client->dev, "%s dest_pos is error. %d > %d\n", - __func__, dest_pos, VCMDRV_MAX_LOG); + __func__, dest_pos, dev_vcm->max_logicalpos); return -EINVAL; } /* calculate move time */ @@ -318,7 +324,7 @@ static int dw9800w_set_ctrl(struct v4l2_ctrl *ctrl) ret = dw9800w_set_pos(dev_vcm, dest_pos); if (dev_vcm->step_mode == LSC_MODE) dev_vcm->move_us = ((dev_vcm->vcm_movefull_t * (uint32_t)move_pos) / - VCMDRV_MAX_LOG); + dev_vcm->max_logicalpos); else dev_vcm->move_us = dev_vcm->vcm_movefull_t; @@ -376,28 +382,27 @@ static const struct v4l2_subdev_internal_ops dw9800w_int_ops = { static void dw9800w_update_vcm_cfg(struct dw9800w_device *dev_vcm) { struct i2c_client *client = dev_vcm->client; - int cur_dist; - if (dev_vcm->max_ma == 0) { + if (dev_vcm->max_current == 0) { dev_err(&client->dev, "max current is zero"); return; } - cur_dist = dev_vcm->vcm_cfg.rated_ma - dev_vcm->vcm_cfg.start_ma; - cur_dist = cur_dist * DW9800W_MAX_REG / dev_vcm->max_ma; - dev_vcm->step = (cur_dist + (VCMDRV_MAX_LOG - 1)) / VCMDRV_MAX_LOG; + if (dev_vcm->vcm_cfg.rated_ma > dev_vcm->max_current) + dev_vcm->max_current = DW9800W_MAX_REG; + dev_vcm->start_current = dev_vcm->vcm_cfg.start_ma * - DW9800W_MAX_REG / dev_vcm->max_ma; + DW9800W_MAX_REG / dev_vcm->max_current; dev_vcm->rated_current = dev_vcm->vcm_cfg.rated_ma * - DW9800W_MAX_REG / dev_vcm->max_ma; + DW9800W_MAX_REG / dev_vcm->max_current; dev_vcm->step_mode = dev_vcm->vcm_cfg.step_mode; dev_info(&client->dev, - "vcm_cfg: %d, %d, %d, max_ma %d\n", + "vcm_cfg: %d, %d, %d, max_current %d\n", dev_vcm->vcm_cfg.start_ma, dev_vcm->vcm_cfg.rated_ma, dev_vcm->vcm_cfg.step_mode, - dev_vcm->max_ma); + dev_vcm->max_current); } static long dw9800w_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) @@ -406,6 +411,7 @@ static long dw9800w_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) struct i2c_client *client = dev_vcm->client; struct rk_cam_vcm_tim *vcm_tim; struct rk_cam_vcm_cfg *vcm_cfg; + unsigned int max_logicalpos; int ret = 0; if (cmd == RK_VIDIOC_VCM_TIMEINFO) { @@ -441,6 +447,16 @@ static long dw9800w_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) dev_vcm->vcm_cfg.rated_ma = vcm_cfg->rated_ma; dev_vcm->vcm_cfg.step_mode = vcm_cfg->step_mode; dw9800w_update_vcm_cfg(dev_vcm); + } else if (cmd == RK_VIDIOC_SET_VCM_MAX_LOGICALPOS) { + max_logicalpos = *(unsigned int *)arg; + + if (max_logicalpos > 0) { + dev_vcm->max_logicalpos = max_logicalpos; + __v4l2_ctrl_modify_range(dev_vcm->focus, + 0, dev_vcm->max_logicalpos, 1, dev_vcm->max_logicalpos); + } + dev_dbg(&client->dev, + "max_logicalpos %d\n", max_logicalpos); } else { dev_err(&client->dev, "cmd 0x%x not supported\n", cmd); @@ -460,6 +476,7 @@ static long dw9800w_compat_ioctl32(struct v4l2_subdev *sd, struct rk_cam_compat_vcm_tim compat_vcm_tim; struct rk_cam_vcm_tim vcm_tim; struct rk_cam_vcm_cfg vcm_cfg; + unsigned int max_logicalpos; long ret; if (cmd == RK_VIDIOC_COMPAT_VCM_TIMEINFO) { @@ -492,6 +509,12 @@ static long dw9800w_compat_ioctl32(struct v4l2_subdev *sd, ret = dw9800w_ioctl(sd, cmd, &vcm_cfg); else ret = -EFAULT; + } else if (cmd == RK_VIDIOC_SET_VCM_MAX_LOGICALPOS) { + ret = copy_from_user(&max_logicalpos, up, sizeof(max_logicalpos)); + if (!ret) + ret = dw9800w_ioctl(sd, cmd, &max_logicalpos); + else + ret = -EFAULT; } else { dev_err(&client->dev, "cmd 0x%x not supported\n", cmd); @@ -528,8 +551,9 @@ static int dw9800w_init_controls(struct dw9800w_device *dev_vcm) v4l2_ctrl_handler_init(hdl, 1); - v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, - 0, VCMDRV_MAX_LOG, 1, 32); + dev_vcm->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, + 0, dev_vcm->max_logicalpos, 1, + dev_vcm->max_logicalpos / 2); if (hdl->error) dev_err(dev_vcm->sd.dev, "%s fail error: 0x%x\n", @@ -585,7 +609,7 @@ static int dw9800w_probe(struct i2c_client *client, { struct device_node *np = of_node_get(client->dev.of_node); struct dw9800w_device *dw9800w_dev; - unsigned int max_ma, start_ma, rated_ma, step_mode; + unsigned int max_current, start_ma, rated_ma, step_mode; unsigned int t_src, t_div; struct v4l2_subdev *sd; char facing[2]; @@ -594,14 +618,14 @@ static int dw9800w_probe(struct i2c_client *client, dev_info(&client->dev, "probing...\n"); if (of_property_read_u32(np, OF_CAMERA_VCMDRV_MAX_CURRENT, - (unsigned int *)&max_ma)) { - max_ma = DW9800W_MAX_CURRENT; + (unsigned int *)&max_current)) { + max_current = DW9800W_MAX_CURRENT; dev_info(&client->dev, "could not get module %s from dts!\n", OF_CAMERA_VCMDRV_MAX_CURRENT); } - if (max_ma == 0) - max_ma = DW9800W_MAX_CURRENT; + if (max_current == 0) + max_current = DW9800W_MAX_CURRENT; if (of_property_read_u32(np, OF_CAMERA_VCMDRV_START_CURRENT, @@ -680,6 +704,7 @@ static int dw9800w_probe(struct i2c_client *client, dw9800w_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; dw9800w_dev->sd.internal_ops = &dw9800w_int_ops; + dw9800w_dev->max_logicalpos = VCMDRV_MAX_LOG; ret = dw9800w_init_controls(dw9800w_dev); if (ret) goto err_cleanup; @@ -704,13 +729,13 @@ static int dw9800w_probe(struct i2c_client *client, if (ret) dev_err(&client->dev, "v4l2 async register subdev failed\n"); - dw9800w_dev->max_ma = max_ma; + dw9800w_dev->max_current = max_current; dw9800w_dev->vcm_cfg.start_ma = start_ma; dw9800w_dev->vcm_cfg.rated_ma = rated_ma; dw9800w_dev->vcm_cfg.step_mode = step_mode; dw9800w_update_vcm_cfg(dw9800w_dev); dw9800w_dev->move_us = 0; - dw9800w_dev->current_related_pos = VCMDRV_MAX_LOG; + dw9800w_dev->current_related_pos = dw9800w_dev->max_logicalpos; dw9800w_dev->start_move_tv = ns_to_kernel_old_timeval(ktime_get_ns()); dw9800w_dev->end_move_tv = ns_to_kernel_old_timeval(ktime_get_ns()); diff --git a/drivers/media/i2c/os02k10.c b/drivers/media/i2c/os02k10.c index 16df5d5972e3..0a064cdd50dd 100644 --- a/drivers/media/i2c/os02k10.c +++ b/drivers/media/i2c/os02k10.c @@ -1806,6 +1806,7 @@ static int os02k10_set_ctrl(struct v4l2_ctrl *ctrl) s64 max; int ret = 0; u32 val = 0; + u32 reg_data; /* Propagate change of current control to all related controls */ switch (ctrl->id) { @@ -1835,23 +1836,53 @@ static int os02k10_set_ctrl(struct v4l2_ctrl *ctrl) } break; case V4L2_CID_ANALOGUE_GAIN: + /* + * dgain reg format is 4.10bits, again reg format is 4.4bits + * 1x is 64, 6 decimal places + */ if (ctrl->val > 992) { - dgain = ctrl->val * 1024 / 992; + dgain = ctrl->val * 1024 / 992; //15.5X * 64 = 992 again = 992; } else { - dgain = 1024; + dgain = 1024; //move 10 bits left again = ctrl->val; } dev_dbg(&client->dev, "gain %d, ag 0x%x, dg 0x%x\n", ctrl->val, again, dgain); - ret = os02k10_write_reg(os02k10->client, + + ret |= os02k10_read_reg(os02k10->client, OS02K10_AEC_LONG_REL_GAIN_REG_H, + OS02K10_REG_VALUE_08BIT, ®_data); + reg_data = reg_data & 0xf0; + ret |= os02k10_write_reg(os02k10->client, OS02K10_AEC_LONG_REL_GAIN_REG_H, - OS02K10_REG_VALUE_16BIT, - (again << 2) & 0xff0); + OS02K10_REG_VALUE_08BIT, + ((again >> 6) & 0x0f) | reg_data); + ret |= os02k10_read_reg(os02k10->client, OS02K10_AEC_LONG_REL_GAIN_REG_L, + OS02K10_REG_VALUE_08BIT, ®_data); + reg_data = reg_data & 0x0f; + ret |= os02k10_write_reg(os02k10->client, + OS02K10_AEC_LONG_REL_GAIN_REG_L, + OS02K10_REG_VALUE_08BIT, + (((again >> 2) & 0x0f) << 4) | reg_data); + + ret |= os02k10_read_reg(os02k10->client, OS02K10_AEC_LONG_DIG_GAIN_REG_H, + OS02K10_REG_VALUE_08BIT, ®_data); + reg_data = reg_data & 0xf0; ret |= os02k10_write_reg(os02k10->client, OS02K10_AEC_LONG_DIG_GAIN_REG_H, - OS02K10_REG_VALUE_24BIT, - (dgain << 6) & 0xfffc0); + OS02K10_REG_VALUE_08BIT, + ((dgain >> 10) & 0x0f) | reg_data); + ret |= os02k10_write_reg(os02k10->client, + OS02K10_AEC_LONG_DIG_GAIN_REG_M, + OS02K10_REG_VALUE_08BIT, + (dgain >> 2) & 0xff); + ret |= os02k10_read_reg(os02k10->client, OS02K10_AEC_LONG_DIG_GAIN_REG_L, + OS02K10_REG_VALUE_08BIT, ®_data); + reg_data = reg_data & 0x3f; + ret |= os02k10_write_reg(os02k10->client, + OS02K10_AEC_LONG_DIG_GAIN_REG_L, + OS02K10_REG_VALUE_08BIT, + ((dgain & 0x03) << 6) | reg_data); break; case V4L2_CID_VBLANK: dev_dbg(&client->dev, "set blank value 0x%x\n", ctrl->val); diff --git a/drivers/media/platform/rockchip/isp/capture_v21.c b/drivers/media/platform/rockchip/isp/capture_v21.c index 9bbade405d26..dcdc859aedb4 100644 --- a/drivers/media/platform/rockchip/isp/capture_v21.c +++ b/drivers/media/platform/rockchip/isp/capture_v21.c @@ -1150,7 +1150,8 @@ static void rdbk_frame_end(struct rkisp_stream *stream) if (!ret) { denominator = sensor->fi.interval.denominator; numerator = sensor->fi.interval.numerator; - time = numerator * 1000 / denominator * 1000 * 1000; + if (denominator) + time = numerator * 1000 / denominator * 1000 * 1000; if (numerator) fps = denominator / numerator; } diff --git a/drivers/media/platform/rockchip/isp/common.c b/drivers/media/platform/rockchip/isp/common.c index 173132560bd7..ff25495c7fc5 100644 --- a/drivers/media/platform/rockchip/isp/common.c +++ b/drivers/media/platform/rockchip/isp/common.c @@ -330,6 +330,11 @@ int rkisp_attach_hw(struct rkisp_device *isp) return -EINVAL; } + if (hw->dev_num >= DEV_MAX) { + dev_err(isp->dev, "failed attach isp hw, max dev:%d\n", DEV_MAX); + return -EINVAL; + } + isp->dev_id = hw->dev_num; hw->isp[hw->dev_num] = isp; hw->dev_num++; diff --git a/drivers/media/platform/rockchip/isp/csi.c b/drivers/media/platform/rockchip/isp/csi.c index ff9b815f9ffc..bd469c40604f 100644 --- a/drivers/media/platform/rockchip/isp/csi.c +++ b/drivers/media/platform/rockchip/isp/csi.c @@ -82,6 +82,8 @@ static int rkisp_csi_link_setup(struct media_entity *entity, id = local->index - 1; if (id && id < RKISP_STREAM_DMATX3) stream = &csi->ispdev->cap_dev.stream[id + 1]; + if (id >= ARRAY_SIZE(csi->sink)) + return -EINVAL; if (flags & MEDIA_LNK_FL_ENABLED) { if (csi->sink[id].linked) { ret = -EBUSY; diff --git a/drivers/media/platform/rockchip/isp/isp_params.c b/drivers/media/platform/rockchip/isp/isp_params.c index ae795152fb2e..753d618847e7 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.c +++ b/drivers/media/platform/rockchip/isp/isp_params.c @@ -210,36 +210,23 @@ static void rkisp_params_vb2_stop_streaming(struct vb2_queue *vq) struct rkisp_device *dev = params_vdev->dev; struct rkisp_buffer *buf; unsigned long flags; - int i; /* stop params input firstly */ spin_lock_irqsave(¶ms_vdev->config_lock, flags); params_vdev->streamon = false; wake_up(&dev->sync_onoff); - spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); - - for (i = 0; i < RKISP_ISP_PARAMS_REQ_BUFS_MAX; i++) { - spin_lock_irqsave(¶ms_vdev->config_lock, flags); - if (!list_empty(¶ms_vdev->params)) { - buf = list_first_entry(¶ms_vdev->params, - struct rkisp_buffer, queue); - list_del(&buf->queue); - spin_unlock_irqrestore(¶ms_vdev->config_lock, - flags); - } else { - spin_unlock_irqrestore(¶ms_vdev->config_lock, - flags); - break; - } - + while (!list_empty(¶ms_vdev->params)) { + buf = list_first_entry(¶ms_vdev->params, + struct rkisp_buffer, queue); + list_del(&buf->queue); vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } - if (params_vdev->cur_buf) { buf = params_vdev->cur_buf; vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); params_vdev->cur_buf = NULL; } + spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); rkisp_params_disable_isp(params_vdev); /* clean module params */ diff --git a/drivers/media/platform/rockchip/isp/isp_params_v21.c b/drivers/media/platform/rockchip/isp/isp_params_v21.c index 509554d63532..6fac6ab466d1 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v21.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v21.c @@ -4337,7 +4337,7 @@ int rkisp_init_params_vdev_v21(struct rkisp_isp_params_vdev *params_vdev) ret = rkisp_alloc_buffer(params_vdev->dev, &priv_val->buf_3dlut[i]); if (ret) { dev_err(dev, "can not alloc buffer\n"); - goto err; + goto err_3dlut; } } @@ -4348,7 +4348,7 @@ int rkisp_init_params_vdev_v21(struct rkisp_isp_params_vdev *params_vdev) ret = rkisp_alloc_buffer(params_vdev->dev, &priv_val->buf_lsclut[i]); if (ret) { dev_err(dev, "can not alloc buffer\n"); - goto err; + goto err_lsclut; } } @@ -4357,15 +4357,16 @@ int rkisp_init_params_vdev_v21(struct rkisp_isp_params_vdev *params_vdev) params_vdev->priv_ops = &rkisp_v21_isp_params_ops; rkisp_clear_first_param_v2x(params_vdev); return 0; - -err: - for (i = 0; i < RKISP_PARAM_3DLUT_BUF_NUM; i++) +err_lsclut: + for (i -= 1; i >= 0; i--) + rkisp_free_buffer(params_vdev->dev, &priv_val->buf_lsclut[i]); + i = RKISP_PARAM_3DLUT_BUF_NUM; +err_3dlut: + for (i -= 1; i >= 0; i--) rkisp_free_buffer(params_vdev->dev, &priv_val->buf_3dlut[i]); - for (i = 0; i < RKISP_PARAM_LSC_LUT_BUF_NUM; i++) - rkisp_free_buffer(params_vdev->dev, &priv_val->buf_lsclut[i]); vfree(params_vdev->isp21_params); - + kfree(priv_val); return ret; } diff --git a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c index c96c4ed9114c..a074bca21b4b 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c @@ -344,6 +344,9 @@ static unsigned long inno_dsidphy_pll_calc_rate(struct inno_dsidphy *inno, * PLL_Output_Frequency: it is equal to DDR-Clock-Frequency * 2 */ fref = prate / 2; + if (!fref) + return 0; + if (rate > 1000000000UL) fout = 1000000000UL; else @@ -357,6 +360,9 @@ static unsigned long inno_dsidphy_pll_calc_rate(struct inno_dsidphy *inno, u64 tmp; u32 delta; + if (!_prediv) + continue; + tmp = (u64)fout * _prediv; do_div(tmp, fref); _fbdiv = tmp; diff --git a/drivers/soc/rockchip/rk_dmabuf_procfs.c b/drivers/soc/rockchip/rk_dmabuf_procfs.c index 0ca0dbde0545..e389449a10ef 100644 --- a/drivers/soc/rockchip/rk_dmabuf_procfs.c +++ b/drivers/soc/rockchip/rk_dmabuf_procfs.c @@ -186,8 +186,10 @@ static int __init rk_dmabuf_init(void) struct proc_dir_entry *root = proc_mkdir("rk_dmabuf", NULL); pdev = platform_device_register_full(&dev_info); - dma_set_max_seg_size(&pdev->dev, (unsigned int)DMA_BIT_MASK(64)); - dmabuf_dev = pdev ? &pdev->dev : NULL; + if (!IS_ERR(pdev)) { + dmabuf_dev = &pdev->dev; + dma_set_max_seg_size(dmabuf_dev, (unsigned int)DMA_BIT_MASK(64)); + } proc_create_single("sgt", 0, root, rk_dmabuf_sgt_show); proc_create_single("dev", 0, root, rk_dmabuf_dev_show); diff --git a/drivers/video/rockchip/rga3/include/rga.h b/drivers/video/rockchip/rga3/include/rga.h index 34a9245d9fd5..2a60a1ae72db 100644 --- a/drivers/video/rockchip/rga3/include/rga.h +++ b/drivers/video/rockchip/rga3/include/rga.h @@ -86,6 +86,12 @@ enum rga_scale_down_mode { RGA_SCALE_DOWN_AVG = 0x1, }; +enum RGA_SCHEDULER_CORE { + RGA_SCHEDULER_RGA3_CORE0 = 1 << 0, + RGA_SCHEDULER_RGA3_CORE1 = 1 << 1, + RGA_SCHEDULER_RGA2_CORE0 = 1 << 2, +}; + /* RGA process mode enum */ enum { BITBLT_MODE = 0x0, diff --git a/drivers/video/rockchip/rga3/include/rga_common.h b/drivers/video/rockchip/rga3/include/rga_common.h index 67aad7b48202..32e83cc9c9f9 100644 --- a/drivers/video/rockchip/rga3/include/rga_common.h +++ b/drivers/video/rockchip/rga3/include/rga_common.h @@ -37,6 +37,7 @@ const char *rga_get_rotate_mode_str(uint8_t mode); const char *rga_get_blend_mode_str(enum rga_alpha_blend_mode mode); const char *rga_get_memory_type_str(uint8_t type); const char *rga_get_mmu_type_str(enum rga_mmu mmu_type); +const char *rga_get_core_name(enum RGA_SCHEDULER_CORE core); void rga_convert_addr(struct rga_img_info_t *img, bool before_vir_get_channel); void rga_swap_pd_mode(struct rga_req *req_rga); diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 309159df6b0a..8792e8d64dfc 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -2323,6 +2323,7 @@ static int rga2_init_reg(struct rga_job *job) struct rga2_req req; int ret = 0; struct rga_scheduler_t *scheduler = NULL; + ktime_t timestamp = ktime_get(); scheduler = job->scheduler; if (unlikely(scheduler == NULL)) { @@ -2396,6 +2397,10 @@ static int rga2_init_reg(struct rga_job *job) return -EINVAL; } + if (DEBUGGER_EN(TIME)) + pr_info("request[%d], generate register cost time %lld us\n", + job->request_id, ktime_us_delta(ktime_get(), timestamp)); + return ret; } @@ -2599,8 +2604,8 @@ static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) rga_read(RGA2_INT, scheduler)); if (DEBUGGER_EN(TIME)) - pr_info("set cmd use time = %lld\n", - ktime_us_delta(now, job->timestamp)); + pr_info("request[%d], set register cost time %lld us\n", + job->request_id, ktime_us_delta(now, job->timestamp)); job->hw_running_time = now; job->hw_recoder_time = now; diff --git a/drivers/video/rockchip/rga3/rga3_reg_info.c b/drivers/video/rockchip/rga3/rga3_reg_info.c index 5c1945b98325..2b61833aa4a3 100644 --- a/drivers/video/rockchip/rga3/rga3_reg_info.c +++ b/drivers/video/rockchip/rga3/rga3_reg_info.c @@ -1955,6 +1955,7 @@ static int rga3_init_reg(struct rga_job *job) struct rga3_req req; int ret = 0; struct rga_scheduler_t *scheduler = NULL; + ktime_t timestamp = ktime_get(); scheduler = job->scheduler; if (unlikely(scheduler == NULL)) { @@ -1984,6 +1985,10 @@ static int rga3_init_reg(struct rga_job *job) return -EINVAL; } + if (DEBUGGER_EN(TIME)) + pr_info("request[%d], generate register cost time %lld us\n", + job->request_id, ktime_us_delta(ktime_get(), timestamp)); + return ret; } @@ -2070,7 +2075,8 @@ static int rga3_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) } if (DEBUGGER_EN(TIME)) - pr_info("set cmd use time = %lld\n", ktime_us_delta(now, job->timestamp)); + pr_info("request[%d], set register cost time %lld us\n", + job->request_id, ktime_us_delta(now, job->timestamp)); job->hw_running_time = now; job->hw_recoder_time = now; diff --git a/drivers/video/rockchip/rga3/rga_common.c b/drivers/video/rockchip/rga3/rga_common.c index 6f8b57921506..80d4821fb321 100644 --- a/drivers/video/rockchip/rga3/rga_common.c +++ b/drivers/video/rockchip/rga3/rga_common.c @@ -604,6 +604,20 @@ const char *rga_get_mmu_type_str(enum rga_mmu mmu_type) } } +const char *rga_get_core_name(enum RGA_SCHEDULER_CORE core) +{ + switch (core) { + case RGA_SCHEDULER_RGA3_CORE0: + return "RGA3_core0"; + case RGA_SCHEDULER_RGA3_CORE1: + return "RGA3_core1"; + case RGA_SCHEDULER_RGA2_CORE0: + return "RGA2_core0"; + default: + return "unknown_core"; + } +} + void rga_convert_addr(struct rga_img_info_t *img, bool before_vir_get_channel) { /* diff --git a/drivers/video/rockchip/rga3/rga_job.c b/drivers/video/rockchip/rga3/rga_job.c index 0093aa2f7c2f..fae613bbf716 100644 --- a/drivers/video/rockchip/rga3/rga_job.c +++ b/drivers/video/rockchip/rga3/rga_job.c @@ -13,6 +13,7 @@ #include "rga_mm.h" #include "rga_iommu.h" #include "rga_debugger.h" +#include "rga_common.h" static void rga_job_free(struct rga_job *job) { @@ -40,12 +41,13 @@ static void rga_job_get(struct rga_job *job) static int rga_job_cleanup(struct rga_job *job) { - if (DEBUGGER_EN(TIME)) - pr_err("(pid:%d) job clean use time = %lld\n", job->pid, - ktime_us_delta(ktime_get(), job->timestamp)); - rga_job_put(job); + if (DEBUGGER_EN(TIME)) + pr_info("request[%d], job cleanup total cost time %lld us\n", + job->request_id, + ktime_us_delta(ktime_get(), job->timestamp)); + return 0; } @@ -272,11 +274,11 @@ struct rga_job *rga_job_done(struct rga_scheduler_t *scheduler) if (DEBUGGER_EN(DUMP_IMAGE)) rga_dump_job_image(job); - if (DEBUGGER_EN(TIME)) { - pr_info("hw use time = %lld\n", ktime_us_delta(now, job->hw_running_time)); - pr_info("(pid:%d) job done use time = %lld\n", job->pid, - ktime_us_delta(now, job->timestamp)); - } + if (DEBUGGER_EN(TIME)) + pr_info("request[%d], hardware[%s] cost time %lld us\n", + job->request_id, + rga_get_core_name(scheduler->core), + ktime_us_delta(now, job->hw_running_time)); rga_mm_unmap_job_info(job); @@ -492,7 +494,7 @@ static bool rga_is_need_current_mm(struct rga_req *req) return false; } -static int rga_request_get_current_mm(struct rga_request *request) +static struct mm_struct *rga_request_get_current_mm(struct rga_request *request) { int i; @@ -500,23 +502,21 @@ static int rga_request_get_current_mm(struct rga_request *request) if (rga_is_need_current_mm(&(request->task_list[i]))) { mmgrab(current->mm); mmget(current->mm); - request->current_mm = current->mm; - break; + return current->mm; } } - return 0; + return NULL; } -static void rga_request_put_current_mm(struct rga_request *request) +static void rga_request_put_current_mm(struct mm_struct *mm) { - if (request->current_mm == NULL) + if (mm == NULL) return; - mmput(request->current_mm); - mmdrop(request->current_mm); - request->current_mm = NULL; + mmput(mm); + mmdrop(mm); } static int rga_request_add_acquire_fence_callback(int acquire_fence_fd, @@ -693,6 +693,7 @@ static int rga_request_scheduler_job_abort(struct rga_request *request) static void rga_request_release_abort(struct rga_request *request, int err_code) { unsigned long flags; + struct mm_struct *current_mm; struct rga_pending_request_manager *request_manager = rga_drvdata->pend_request_manager; if (rga_request_scheduler_job_abort(request) > 0) @@ -707,11 +708,13 @@ static void rga_request_release_abort(struct rga_request *request, int err_code) request->is_running = false; request->is_done = false; - - rga_request_put_current_mm(request); + current_mm = request->current_mm; + request->current_mm = NULL; spin_unlock_irqrestore(&request->lock, flags); + rga_request_put_current_mm(current_mm); + rga_dma_fence_signal(request->release_fence, err_code); mutex_lock(&request_manager->lock); @@ -848,12 +851,34 @@ int rga_request_commit(struct rga_request *request) static void rga_request_acquire_fence_signaled_cb(struct dma_fence *fence, struct dma_fence_cb *_waiter) { + int ret; + unsigned long flags; + struct mm_struct *current_mm; struct rga_fence_waiter *waiter = (struct rga_fence_waiter *)_waiter; struct rga_request *request = (struct rga_request *)waiter->private; struct rga_pending_request_manager *request_manager = rga_drvdata->pend_request_manager; - if (rga_request_commit(request)) - pr_err("rga request[%d] commit failed!\n", request->id); + ret = rga_request_commit(request); + if (ret < 0) { + pr_err("acquire_fence callback: rga request[%d] commit failed!\n", request->id); + + spin_lock_irqsave(&request->lock, flags); + + request->is_running = false; + current_mm = request->current_mm; + request->current_mm = NULL; + + spin_unlock_irqrestore(&request->lock, flags); + + rga_request_put_current_mm(current_mm); + + /* + * Since the callback is called while holding &dma_fence.lock, + * the _locked API is used here. + */ + if (dma_fence_get_status_locked(request->release_fence) == 0) + dma_fence_signal_locked(request->release_fence); + } mutex_lock(&request_manager->lock); rga_request_put(request); @@ -866,6 +891,7 @@ int rga_request_release_signal(struct rga_scheduler_t *scheduler, struct rga_job { struct rga_pending_request_manager *request_manager; struct rga_request *request; + struct mm_struct *current_mm; int finished_count, failed_count; bool is_finished = false; unsigned long flags; @@ -902,18 +928,18 @@ int rga_request_release_signal(struct rga_scheduler_t *scheduler, struct rga_job spin_unlock_irqrestore(&request->lock, flags); - rga_job_cleanup(job); - if ((failed_count + finished_count) >= request->task_count) { spin_lock_irqsave(&request->lock, flags); request->is_running = false; request->is_done = true; - - rga_request_put_current_mm(request); + current_mm = request->current_mm; + request->current_mm = NULL; spin_unlock_irqrestore(&request->lock, flags); + rga_request_put_current_mm(current_mm); + rga_dma_fence_signal(request->release_fence, request->ret); is_finished = true; @@ -937,6 +963,13 @@ int rga_request_release_signal(struct rga_scheduler_t *scheduler, struct rga_job mutex_unlock(&request_manager->lock); + if (DEBUGGER_EN(TIME)) + pr_info("request[%d], job done total cost time %lld us\n", + job->request_id, + ktime_us_delta(ktime_get(), job->timestamp)); + + rga_job_cleanup(job); + return 0; } @@ -1066,6 +1099,9 @@ int rga_request_submit(struct rga_request *request) int ret = 0; unsigned long flags; struct dma_fence *release_fence; + struct mm_struct *current_mm; + + current_mm = rga_request_get_current_mm(request); spin_lock_irqsave(&request->lock, flags); @@ -1073,14 +1109,16 @@ int rga_request_submit(struct rga_request *request) spin_unlock_irqrestore(&request->lock, flags); pr_err("can not re-config when request is running\n"); - return -EFAULT; + ret = -EFAULT; + goto err_put_current_mm; } if (request->task_list == NULL) { spin_unlock_irqrestore(&request->lock, flags); pr_err("can not find task list from id[%d]\n", request->id); - return -EINVAL; + ret = -EINVAL; + goto err_put_current_mm; } /* Reset */ @@ -1088,8 +1126,7 @@ int rga_request_submit(struct rga_request *request) request->is_done = false; request->finished_task_count = 0; request->failed_task_count = 0; - - rga_request_get_current_mm(request); + request->current_mm = current_mm; /* Unlock after ensuring that the current request will not be resubmitted. */ spin_unlock_irqrestore(&request->lock, flags); @@ -1099,7 +1136,7 @@ int rga_request_submit(struct rga_request *request) if (IS_ERR(release_fence)) { pr_err("Can not alloc release fence!\n"); ret = IS_ERR(release_fence); - goto error_put_current_mm; + goto err_reset_request; } request->release_fence = release_fence; @@ -1148,14 +1185,17 @@ err_put_release_fence: request->release_fence = NULL; } -error_put_current_mm: +err_reset_request: spin_lock_irqsave(&request->lock, flags); - rga_request_put_current_mm(request); + request->current_mm = NULL; request->is_running = false; spin_unlock_irqrestore(&request->lock, flags); +err_put_current_mm: + rga_request_put_current_mm(current_mm); + return ret; } @@ -1244,6 +1284,7 @@ int rga_request_free(struct rga_request *request) static void rga_request_kref_release(struct kref *ref) { struct rga_request *request; + struct mm_struct *current_mm; unsigned long flags; request = container_of(ref, struct rga_request, refcount); @@ -1253,16 +1294,22 @@ static void rga_request_kref_release(struct kref *ref) spin_lock_irqsave(&request->lock, flags); - rga_request_put_current_mm(request); rga_dma_fence_put(request->release_fence); + current_mm = request->current_mm; + request->current_mm = NULL; if (!request->is_running || request->is_done) { spin_unlock_irqrestore(&request->lock, flags); + + rga_request_put_current_mm(current_mm); + goto free_request; } spin_unlock_irqrestore(&request->lock, flags); + rga_request_put_current_mm(current_mm); + rga_request_scheduler_job_abort(request); free_request: diff --git a/drivers/video/rockchip/rga3/rga_mm.c b/drivers/video/rockchip/rga3/rga_mm.c index 94b54d45af08..140952459f11 100644 --- a/drivers/video/rockchip/rga3/rga_mm.c +++ b/drivers/video/rockchip/rga3/rga_mm.c @@ -840,6 +840,11 @@ static int rga_mm_handle_remove(int id, void *ptr, void *data) return 0; } +static void rga_mm_buffer_destroy(struct rga_internal_buffer *buffer) +{ + rga_mm_kref_release_buffer(&buffer->refcount); +} + static struct rga_internal_buffer * rga_mm_lookup_external(struct rga_mm *mm_session, struct rga_external_buffer *external_buffer, @@ -1991,6 +1996,7 @@ error_unmap_buffer: int rga_mm_map_job_info(struct rga_job *job) { int ret; + ktime_t timestamp = ktime_get(); if (job->flags & RGA_JOB_USE_HANDLE) { ret = rga_mm_get_handle_info(job); @@ -1998,12 +2004,20 @@ int rga_mm_map_job_info(struct rga_job *job) pr_err("failed to get buffer from handle\n"); return ret; } + + if (DEBUGGER_EN(TIME)) + pr_info("request[%d], get buffer_handle info cost %lld us\n", + job->request_id, ktime_us_delta(ktime_get(), timestamp)); } else { ret = rga_mm_map_buffer_info(job); if (ret < 0) { pr_err("failed to map buffer\n"); return ret; } + + if (DEBUGGER_EN(TIME)) + pr_info("request[%d], map buffer cost %lld us\n", + job->request_id, ktime_us_delta(ktime_get(), timestamp)); } return 0; @@ -2011,10 +2025,21 @@ int rga_mm_map_job_info(struct rga_job *job) void rga_mm_unmap_job_info(struct rga_job *job) { - if (job->flags & RGA_JOB_USE_HANDLE) + ktime_t timestamp = ktime_get(); + + if (job->flags & RGA_JOB_USE_HANDLE) { rga_mm_put_handle_info(job); - else + + if (DEBUGGER_EN(TIME)) + pr_info("request[%d], put buffer_handle info cost %lld us\n", + job->request_id, ktime_us_delta(ktime_get(), timestamp)); + } else { rga_mm_unmap_buffer_info(job); + + if (DEBUGGER_EN(TIME)) + pr_info("request[%d], unmap buffer cost %lld us\n", + job->request_id, ktime_us_delta(ktime_get(), timestamp)); + } } uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer, @@ -2142,9 +2167,9 @@ int rga_mm_session_release_buffer(struct rga_session *session) idr_for_each_entry(&mm->memory_idr, buffer, i) { if (session == buffer->session) { - pr_err("[tgid:%d] Decrement the reference of handle[%d] when the user exits\n", + pr_err("[tgid:%d] Destroy handle[%d] when the user exits\n", session->tgid, buffer->handle); - kref_put(&buffer->refcount, rga_mm_kref_release_buffer); + rga_mm_buffer_destroy(buffer); } }