diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index bc9652a02024..eac34da215f2 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -684,14 +684,14 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, } dp->plat_data.encoder = &dp->encoder.encoder; + + rockchip_dp_drm_self_refresh_helper_init(dp); } ret = analogix_dp_bind(dp->adp, drm_dev); if (ret) goto err_unregister_audio_pdev; - rockchip_dp_drm_self_refresh_helper_init(dp); - return 0; err_unregister_audio_pdev: @@ -707,7 +707,8 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, if (dp->audio_pdev) platform_device_unregister(dp->audio_pdev); - rockchip_dp_drm_self_refresh_helper_cleanup(dp); + if (!dp->plat_data.left) + rockchip_dp_drm_self_refresh_helper_cleanup(dp); analogix_dp_unbind(dp->adp); dp->encoder.encoder.funcs->destroy(&dp->encoder.encoder); } diff --git a/drivers/media/i2c/max96756.c b/drivers/media/i2c/max96756.c index 42b18c9aaee6..ff642a7a50a1 100644 --- a/drivers/media/i2c/max96756.c +++ b/drivers/media/i2c/max96756.c @@ -11,6 +11,9 @@ * * V0.0X01.0X02 * - Compatible with kernel-6.1 version + * + * V0.0X01.0X03 + * - Add writing EDID tables */ #define DEBUG @@ -40,7 +43,7 @@ #include #include "max96756.h" -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) static int debug; module_param(debug, int, 0644); @@ -64,12 +67,14 @@ MODULE_PARM_DESC(debug, "debug level (0-3)"); #define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default" #define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep" +#define MAX96756_WRITEEDID_ENABLE "rockchip,max96756-writeedid-enable" #define MAX96756_REG_VALUE_08BIT 1 #define MAX96756_REG_VALUE_16BIT 2 #define MAX96756_NAME "max96756" #define MAX96756_MEDIA_BUS_FMT MEDIA_BUS_FMT_BGR888_1X24 +#define MAX96745_I2CADDR 0x40 static const char *const max96756_supply_names[] = { "vcc1v2", /* Analog power */ @@ -77,6 +82,27 @@ static const char *const max96756_supply_names[] = { }; #define MAX96756_NUM_SUPPLIES ARRAY_SIZE(max96756_supply_names) +#define MAX96756_EDID_COUNT 256 + +static const u8 edid_1080p60_720p_480p_rgb888[MAX96756_EDID_COUNT] = { +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x34, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x01, 0x04, 0xA5, 0xF0, 0x90, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, +0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x3A, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, 0x58, 0x2C, +0x45, 0x00, 0x40, 0x44, 0x21, 0x00, 0x00, 0x18, 0x01, 0x1D, 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20, +0x6E, 0x28, 0x55, 0x00, 0x40, 0x44, 0x21, 0x00, 0x00, 0x18, 0x8C, 0x0A, 0xD0, 0x8A, 0x20, 0xE0, +0x2D, 0x10, 0x10, 0x3E, 0x96, 0x00, 0x40, 0x44, 0x21, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7F, +0x02, 0x03, 0x09, 0xF3, 0x40, 0x23, 0x09, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85 +}; + static struct rkmodule_csi_dphy_param rk3588_dcphy_param = { .vendor = PHY_VENDOR_SAMSUNG, .lp_vol_ref = 3, @@ -95,6 +121,11 @@ struct regval { u16 delay; }; +struct edid_msg { + u32 max_width; + const u8 *edid_list; +}; + struct max96756_mode { u32 width; u32 height; @@ -156,6 +187,9 @@ struct max96756 { const char *module_facing; const char *module_name; const char *len_name; + + bool writeedid_enable; + const struct edid_msg *cur_edid_msg; }; #define to_max96756(sd) container_of(sd, struct max96756, subdev) @@ -238,6 +272,29 @@ static const struct regval max96756_mipi_1080p_60fps[] = { { 0x48, REG_NULL, 0x00, 0x00 }, }; +static const struct regval max96745_reconfig_begin[] = { + + { 0x40, 0x7000, 0x00, 0x00 }, // Disable LINK_ENABLE + { 0x40, 0x6422, 0x05, 0x00 }, + { 0x40, REG_NULL, 0x00, 0x00 }, +}; + +static const struct regval max96745_reconfig_end[] = { + + { 0x40, 0x6422, 0x73, 0x00 }, + { 0x40, 0x7054, 0x03, 0x32 }, // video input and link reset + { 0x40, 0x7000, 0x01, 0x00 }, // Enable LINK_ENABLE + { 0x48, 0x0010, 0x25, 0x32 }, // max96756 reset one shot + { 0x48, REG_NULL, 0x00, 0x00 }, +}; + +static const struct edid_msg edid_msgs[] = { + { + .max_width = 1920, + .edid_list = edid_1080p60_720p_480p_rgb888, + }, +}; + static const struct max96756_mode supported_modes[] = { { .width = 1920, @@ -249,6 +306,26 @@ static const struct max96756_mode supported_modes[] = { .reg_list = max96756_mipi_1080p_60fps, .link_freq_idx = 0, }, + { + .width = 1280, + .height = 720, + .max_fps = { + .numerator = 10000, + .denominator = 600000, + }, + .reg_list = max96756_mipi_1080p_60fps, + .link_freq_idx = 0, + }, + { + .width = 720, + .height = 480, + .max_fps = { + .numerator = 10000, + .denominator = 600000, + }, + .reg_list = max96756_mipi_1080p_60fps, + .link_freq_idx = 0, + }, }; static const struct max96756_mode supported_modes_dcphy[] = { @@ -352,6 +429,40 @@ static int max96756_read_reg(struct i2c_client *client, u16 reg, return 0; } +static int max96756_write_reg_burst(struct i2c_client *client, u16 reg, + const u8 *val) +{ + struct i2c_msg msgs[1]; + int ret; + int total_len = 2 + MAX96756_EDID_COUNT; + u8 *buf; + + buf = kzalloc(total_len, GFP_KERNEL); + if (buf == NULL) { + dev_err(&client->dev, "Failed to allocate bytes\n"); + return -ENOMEM; + } + + buf[0] = (reg >> 8) & 0xff; + buf[1] = reg & 0xff; + memcpy(&buf[2], val, MAX96756_EDID_COUNT); + + /* Fill msg struct */ + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = total_len; + msgs[0].buf = buf; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) { + kfree(buf); + return -EIO; + } + + kfree(buf); + return 0; +} + static int max96756_get_reso_dist(const struct max96756_mode *mode, struct v4l2_mbus_framefmt *framefmt) { @@ -727,6 +838,59 @@ static int max96756_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, } } +static int max96745_reconfig_edid(struct max96756 *max96756) +{ + int ret = -1; + u32 val = 0, i, flag = 0; + unsigned short temp_addr = 0; + + temp_addr = max96756->client->addr; + + //wait for link lock + for (i = 0; i < 10; i++) { // Maximum waiting time 100ms + max96756_read_reg(max96756->client, 0x0013, + MAX96756_REG_VALUE_08BIT, &val); + if (val & (1 << 3)) { + dev_dbg(&max96756->client->dev, "serdes reg locked 0x%x\n", val); + flag = 1; + break; + } + usleep_range(10000, 10100); + } + + if (flag != 1) { + dev_err(&max96756->client->dev, "%s: serdes reg still not locked ", __func__); + return ret; + } + + //common begin + ret = max96756_write_array(max96756->client, + max96745_reconfig_begin); + if (ret) { + dev_err(&max96756->client->dev, "max96745_reconfig_begin err\n"); + max96756->client->addr = temp_addr; + return ret; + } + + //write edid table + max96756->client->addr = MAX96745_I2CADDR; + ret = max96756_write_reg_burst(max96756->client, 0x6500, max96756->cur_edid_msg->edid_list); + if (ret) { + dev_err(&max96756->client->dev, "edid_table err\n"); + max96756->client->addr = temp_addr; + return ret; + } + + //common end + ret = max96756_write_array(max96756->client, + max96745_reconfig_end); + if (ret) + dev_err(&max96756->client->dev, "max96745_reconfig_end err\n"); + + max96756->client->addr = temp_addr; + return ret; +} + static int __max96756_start_stream(struct max96756 *max96756) { int ret; @@ -739,10 +903,16 @@ static int __max96756_start_stream(struct max96756 *max96756) return ret; } + if (max96756->writeedid_enable) { + ret = max96745_reconfig_edid(max96756); + if (ret) { + dev_err(&max96756->client->dev, "Failed to write edid\n"); + return ret; + } + } + /* In case these controls are set before streaming */ - mutex_unlock(&max96756->mutex); - ret = v4l2_ctrl_handler_setup(&max96756->ctrl_handler); - mutex_lock(&max96756->mutex); + ret = __v4l2_ctrl_handler_setup(&max96756->ctrl_handler); if (ret) { dev_warn(&max96756->client->dev, "Failed to setup ctrl\n"); return ret; @@ -1329,6 +1499,8 @@ static int max96756_probe(struct i2c_client *client) max96756->client = client; max96756->cur_mode = &supported_modes[0]; + max96756->writeedid_enable = of_property_read_bool(node, MAX96756_WRITEEDID_ENABLE); + max96756->cur_edid_msg = &edid_msgs[0]; max96756->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); if (IS_ERR(max96756->pwdn_gpio)) diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index c320465737b0..f699966f89cb 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -257,23 +257,6 @@ static const unsigned int rk628_csi_extcon_cable[] = { EXTCON_NONE, }; -static const struct mipi_timing rk628d_csi_mipi = { - 0x0b, 0x53, 0x10, 0x5b, 0x0b, 0x43, 0x2c, 0x50, 0x0f -}; - -static const struct mipi_timing rk628f_csi0_mipi = { - 0x0b, 0x53, 0x10, 0x5b, 0x0b, 0x43, 0x2c, 0x50, 0x0f -}; - -static const struct mipi_timing rk628f_csi1_mipi = { -//data_lp, data-pre, data-zero, data-trail, clk_lp, clk-pre, clk-zero, clk-trail, clk-post - 0x0b, 0x53, 0x10, 0x5b, 0x0b, 0x43, 0x2c, 0x50, 0x0f -}; - -static const struct mipi_timing rk628f_dsi0_mipi = { - 0x10, 0x70, 0x1c, 0x7f, 0x10, 0x70, 0x3f, 0x7f, 0x1f -}; - static struct rkmodule_csi_dphy_param rk3588_dcphy_param = { .vendor = PHY_VENDOR_SAMSUNG, .lp_vol_ref = 0, @@ -466,6 +449,14 @@ static int rk628_csi_get_detected_timings(struct v4l2_subdev *sd, if (ret) return ret; + v4l2_dbg(1, debug, sd, "hfp:%d, hs:%d, hbp:%d, vfp:%d, vs:%d, vbp:%d, interlace:%d\n", + bt->hfrontporch, bt->hsync, bt->hbackporch, bt->vfrontporch, bt->vsync, + bt->vbackporch, bt->interlaced); + + csi->src_timings = *timings; + if (csi->scaler_en) + *timings = csi->timings; + if ((bt->pixelclock > 300000000 && csi->rk628->version >= RK628F_VERSION) || (bt->width > 2048 && csi->plat_data->tx_mode == DSI_MODE)) { v4l2_info(sd, "rk628f detect pixclk more than 300M, use dual mipi mode\n"); @@ -475,14 +466,6 @@ static int rk628_csi_get_detected_timings(struct v4l2_subdev *sd, csi->rk628->dual_mipi = false; } - v4l2_dbg(1, debug, sd, "hfp:%d, hs:%d, hbp:%d, vfp:%d, vs:%d, vbp:%d, interlace:%d\n", - bt->hfrontporch, bt->hsync, bt->hbackporch, bt->vfrontporch, bt->vsync, - bt->vbackporch, bt->interlaced); - - csi->src_timings = *timings; - if (csi->scaler_en) - *timings = csi->timings; - return ret; } @@ -1018,6 +1001,16 @@ static void rk628_post_process_setup(struct v4l2_subdev *sd) dst.vback_porch = dst_bt->vbackporch; dst.pixelclock = dst_bt->pixelclock; + if (csi->scaler_en) { + dst.vfront_porch = DIV_ROUND_UP(src.vfront_porch * dst_bt->height, src.vactive); + dst.vsync_len = DIV_ROUND_UP(src.vsync_len * dst_bt->height, src.vactive); + dst.vback_porch = DIV_ROUND_UP(src.vback_porch * dst_bt->height, src.vactive); + v4l2_info(sd, "%s: src timing: vfp: %d, vs: %d, vbp: %d\n", + __func__, src.vfront_porch, src.vsync_len, src.vback_porch); + v4l2_info(sd, "%s: dst timing: vfp: %d, vs: %d, vbp: %d\n", + __func__, dst.vfront_porch, dst.vsync_len, dst.vback_porch); + } + rk628_post_process_en(csi->rk628, &src, &dst, &dst_pclk); dst_bt->pixelclock = dst_pclk; } @@ -1488,17 +1481,6 @@ static void rk628_csi_initial_setup(struct v4l2_subdev *sd) struct rk628_csi *csi = to_csi(sd); rk628_csi_initial(sd); - if (csi->rk628->version >= RK628F_VERSION) { - csi->rk628->mipi_timing[0] = rk628f_csi0_mipi; - csi->rk628->mipi_timing[1] = rk628f_csi1_mipi; - } else { - csi->rk628->mipi_timing[0] = rk628d_csi_mipi; - } - - if (csi->plat_data->tx_mode == DSI_MODE) { - csi->rk628->mipi_timing[0] = rk628f_dsi0_mipi; - csi->rk628->mipi_timing[1] = rk628f_dsi0_mipi; - } csi->rk628->dphy_lane_en = 0x1f; csi->txphy_pwron = true; @@ -2156,11 +2138,37 @@ static int rk628_csi_enum_frame_interval(struct v4l2_subdev *sd, return 0; } +static u32 rk628_csi_get_lane_rate_mbps(struct rk628_csi *csi) +{ + u32 lane_rate; + u32 max_lane_rate = 1300; + u8 bpp, lanes; + u64 pixelclock = csi->timings.bt.pixelclock; + + bpp = 16; + lanes = csi->csi_lanes_in_use; + pixelclock = div_u64(pixelclock, 1000 * 1000); + lane_rate = pixelclock * bpp; + lane_rate = div_u64(lane_rate, lanes); + if (csi->rk628->dual_mipi) + lane_rate /= 2; + + if (lane_rate > 1300) + lane_rate = max_lane_rate; + else if (lane_rate > 700 && lane_rate <= 1300) + lane_rate = 1300; + else + lane_rate = 700; + + return lane_rate; +} + static int rk628_csi_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) { struct rk628_csi *csi = to_csi(sd); + u32 rate; if (!tx_5v_power_present(sd) || csi->nosignal) { v4l2_info(sd, "%s hdmirx no signal\n", __func__); @@ -2178,47 +2186,24 @@ static int rk628_csi_get_fmt(struct v4l2_subdev *sd, V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE; if (csi->plat_data->tx_mode == CSI_MODE) { - if (csi->timings.bt.pixelclock > 150000000 || csi->csi_lanes_in_use <= 2) { - v4l2_dbg(1, debug, sd, - "%s res wxh:%dx%d, link freq:%llu, pixrate:%u\n", - __func__, csi->timings.bt.width, csi->timings.bt.height, - link_freq_menu_items[1], RK628_CSI_PIXEL_RATE_HIGH); - __v4l2_ctrl_s_ctrl(csi->link_freq, 1); - __v4l2_ctrl_s_ctrl_int64(csi->pixel_rate, - RK628_CSI_PIXEL_RATE_HIGH); - } else { - v4l2_dbg(1, debug, sd, - "%s res wxh:%dx%d, link freq:%llu, pixrate:%u\n", - __func__, csi->timings.bt.width, csi->timings.bt.height, - link_freq_menu_items[0], RK628_CSI_PIXEL_RATE_LOW); - __v4l2_ctrl_s_ctrl(csi->link_freq, 0); - __v4l2_ctrl_s_ctrl_int64(csi->pixel_rate, - RK628_CSI_PIXEL_RATE_LOW); - } + rate = rk628_csi_get_lane_rate_mbps(csi); } else { - u32 rate; - csi->dsi.rk628 = csi->rk628; csi->dsi.timings = csi->timings; rate = rk628_dsi_get_lane_rate_mbps(&csi->dsi); - v4l2_dbg(1, debug, sd, "%s mipi bitrate:%u mbps\n", __func__, rate); - - if (rate > 1300) { - csi->rk628->mipi_timing[0] = rk628f_dsi0_mipi; - csi->rk628->mipi_timing[1] = rk628f_dsi0_mipi; - __v4l2_ctrl_s_ctrl(csi->link_freq, 2); - } else if (rate <= 1300 && rate > 700) { - csi->rk628->mipi_timing[0] = rk628f_csi0_mipi; - csi->rk628->mipi_timing[1] = rk628f_csi0_mipi; - __v4l2_ctrl_s_ctrl(csi->link_freq, 1); - } else { - csi->rk628->mipi_timing[0] = rk628f_csi0_mipi; - csi->rk628->mipi_timing[1] = rk628f_csi0_mipi; - __v4l2_ctrl_s_ctrl(csi->link_freq, 0); - } - __v4l2_ctrl_s_ctrl_int64(csi->pixel_rate, RK628_CSI_PIXEL_RATE_HIGH); } + v4l2_dbg(1, debug, sd, "%s mipi bitrate:%u mbps\n", __func__, rate); + + if (rate > 1300) + __v4l2_ctrl_s_ctrl(csi->link_freq, 2); + else if (rate <= 1300 && rate > 700) + __v4l2_ctrl_s_ctrl(csi->link_freq, 1); + else + __v4l2_ctrl_s_ctrl(csi->link_freq, 0); + + __v4l2_ctrl_s_ctrl_int64(csi->pixel_rate, RK628_CSI_PIXEL_RATE_HIGH); + mutex_unlock(&csi->confctl_mutex); v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field code:%d\n", __func__, format->format.code, format->format.width, @@ -2649,19 +2634,13 @@ static int mipi_dphy_power_on(struct rk628_csi *csi) struct v4l2_subdev *sd = &csi->sd; int ret; - if (csi->timings.bt.pixelclock > 150000000 || csi->csi_lanes_in_use <= 2) { - csi->lane_mbps = MIPI_DATARATE_MBPS_HIGH; - } else { - csi->lane_mbps = MIPI_DATARATE_MBPS_LOW; - } - if (csi->rk628->dual_mipi) - csi->lane_mbps = MIPI_DATARATE_MBPS_HIGH; + csi->lane_mbps = rk628_csi_get_lane_rate_mbps(csi); bus_width = csi->lane_mbps << 8; bus_width |= COMBTXPHY_MODULEA_EN; if (csi->rk628->version >= RK628F_VERSION) bus_width |= COMBTXPHY_MODULEB_EN; - v4l2_dbg(1, debug, sd, "%s mipi bitrate:%llu mbps\n", __func__, - csi->lane_mbps); + v4l2_info(sd, "%s mipi bitrate:%llu mbps\n", __func__, csi->lane_mbps); + rk628_mipi_dphy_reset_assert(csi->rk628); rk628_mipi_dphy_reset_deassert(csi->rk628); @@ -2672,18 +2651,6 @@ static int mipi_dphy_power_on(struct rk628_csi *csi) if (csi->rk628->version >= RK628F_VERSION) rk628_mipi_dphy_init_hsfreqrange(csi->rk628, csi->lane_mbps, 1); - if (csi->rk628->dual_mipi) { - rk628_mipi_dphy_init_hsmanual(csi->rk628, true, 0); - rk628_mipi_dphy_init_hsmanual(csi->rk628, true, 1); - } else if (csi->lane_mbps == MIPI_DATARATE_MBPS_HIGH && !csi->rk628->dual_mipi) { - rk628_mipi_dphy_init_hsmanual(csi->rk628, true, 0); - if (csi->rk628->version >= RK628F_VERSION) - rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 1); - } else { - rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 0); - if (csi->rk628->version >= RK628F_VERSION) - rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 1); - } rk628_txphy_power_on(csi->rk628); usleep_range(1500, 2000); diff --git a/drivers/media/i2c/rk628/rk628_dsi.c b/drivers/media/i2c/rk628/rk628_dsi.c index af2ab7e5b50a..4255c57c536a 100644 --- a/drivers/media/i2c/rk628/rk628_dsi.c +++ b/drivers/media/i2c/rk628/rk628_dsi.c @@ -88,11 +88,6 @@ static void mipi_dphy_power_on_dsi(struct rk628_dsi *dsi, uint8_t mipi_id) rk628_testif_testclr_deassert(dsi->rk628, mipi_id); rk628_mipi_dphy_init_hsfreqrange(dsi->rk628, dsi->lane_mbps, mipi_id); - if (dsi->lane_mbps > 1100) - rk628_mipi_dphy_init_hsmanual(dsi->rk628, true, mipi_id); - else - rk628_mipi_dphy_init_hsmanual(dsi->rk628, false, mipi_id); - dsi_update_bits(rk628, mipi_id, DSI_PHY_RSTZ, PHY_ENABLECLK, PHY_ENABLECLK); dsi_update_bits(rk628, mipi_id, DSI_PHY_RSTZ, diff --git a/drivers/media/i2c/rk628/rk628_mipi_dphy.c b/drivers/media/i2c/rk628/rk628_mipi_dphy.c index 22e4d2984610..38809ef50f13 100644 --- a/drivers/media/i2c/rk628/rk628_mipi_dphy.c +++ b/drivers/media/i2c/rk628/rk628_mipi_dphy.c @@ -104,6 +104,15 @@ u8 rk628_testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t m } EXPORT_SYMBOL(rk628_testif_write); +static void rk628_testif_set_timing(struct rk628 *rk628, u8 addr, + u8 max, u8 val, uint8_t mipi_id) +{ + if (val > max) + return; + + rk628_testif_write(rk628, addr, (max + 1) | val, mipi_id); +} + u8 rk628_testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id) { u8 test_data; @@ -170,6 +179,56 @@ static inline void mipi_dphy_rstz_deassert(struct rk628 *rk628) udelay(1); } +static void rk628_mipi_dphy_set_timing(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id) +{ + const struct { + unsigned int min_lane_mbps; + unsigned int max_lane_mbps; + u8 clk_lp; + u8 clk_hs_prepare; + u8 clk_hs_zero; + u8 clk_hs_trail; + u8 clk_post; + u8 data_lp; + u8 data_hs_prepare; + u8 data_hs_zero; + u8 data_hs_trail; + } timing_table[] = { + {800, 899, 0x07, 0x30, 0x25, 0x3c, 0x0f, 0x07, 0x40, 0x09, 0x40}, + {1100, 1249, 0x0a, 0x43, 0x2c, 0x50, 0x0f, 0x0a, 0x43, 0x10, 0x55}, + {1250, 1349, 0x0b, 0x43, 0x2c, 0x50, 0x0f, 0x0b, 0x53, 0x10, 0x5b}, + {1350, 1449, 0x0c, 0x43, 0x36, 0x60, 0x0f, 0x0c, 0x53, 0x10, 0x65}, + {1450, 1500, 0x0f, 0x60, 0x31, 0x60, 0x0f, 0x0e, 0x60, 0x11, 0x6a}, + {1750, 2050, 0x10, 0x70, 0x3f, 0x7f, 0x1f, 0x10, 0x70, 0x1c, 0x7f}, + }; + unsigned int index; + + // These ranges use the controller's internal automatically calculated timing. + if (lane_mbps < 800 || (lane_mbps >= 900 && lane_mbps < 1100)) + return; + + if (lane_mbps < timing_table[0].min_lane_mbps) + return; + + for (index = 0; index < ARRAY_SIZE(timing_table); index++) + if (lane_mbps >= timing_table[index].min_lane_mbps && + lane_mbps < timing_table[index].max_lane_mbps) + break; + + if (index == ARRAY_SIZE(timing_table)) + --index; + + rk628_testif_set_timing(rk628, 0x60, 0x3f, timing_table[index].clk_lp, mipi_id); + rk628_testif_set_timing(rk628, 0x61, 0x7f, timing_table[index].clk_hs_prepare, mipi_id); + rk628_testif_set_timing(rk628, 0x62, 0x3f, timing_table[index].clk_hs_zero, mipi_id); + rk628_testif_set_timing(rk628, 0x63, 0x7f, timing_table[index].clk_hs_trail, mipi_id); + rk628_testif_set_timing(rk628, 0x65, 0x0f, timing_table[index].clk_post, mipi_id); + rk628_testif_set_timing(rk628, 0x70, 0x3f, timing_table[index].data_lp, mipi_id); + rk628_testif_set_timing(rk628, 0x71, 0x7f, timing_table[index].data_hs_prepare, mipi_id); + rk628_testif_set_timing(rk628, 0x72, 0x3f, timing_table[index].data_hs_zero, mipi_id); + rk628_testif_set_timing(rk628, 0x73, 0x7f, timing_table[index].data_hs_trail, mipi_id); +} + void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id) { const struct { @@ -199,43 +258,10 @@ void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_ hsfreqrange = hsfreqrange_table[index].hsfreqrange; rk628_testif_write(rk628, 0x44, HSFREQRANGE(hsfreqrange), mipi_id); + rk628_mipi_dphy_set_timing(rk628, lane_mbps, mipi_id); } EXPORT_SYMBOL(rk628_mipi_dphy_init_hsfreqrange); -void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mipi_id) -{ - dev_info(rk628->dev, - "mipi dphy%d hs config, manual: %s\n", mipi_id, manual ? "true" : "false"); - //config mipi timing when mipi freq is 1250Mbps - rk628_testif_write(rk628, 0x70, - manual ? (HSZERO(rk628->mipi_timing[mipi_id].data_lp) | BIT(6)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x71, - manual ? (HSTX(rk628->mipi_timing[mipi_id].data_prepare) | BIT(7)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x72, - manual ? (HSZERO(rk628->mipi_timing[mipi_id].data_zero) | BIT(6)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x73, - manual ? (HSTX(rk628->mipi_timing[mipi_id].data_trail) | BIT(7)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x60, - manual ? (HSZERO(rk628->mipi_timing[mipi_id].clk_lp) | BIT(6)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x61, - manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_prepare) | BIT(7)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x62, - manual ? (HSZERO(rk628->mipi_timing[mipi_id].clk_zero) | BIT(6)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x63, - manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_trail) | BIT(7)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x65, - manual ? (HSPOST(rk628->mipi_timing[mipi_id].clk_post) | BIT(4)) : 0, mipi_id); -} -EXPORT_SYMBOL(rk628_mipi_dphy_init_hsmanual); - int rk628_mipi_dphy_reset_assert(struct rk628 *rk628) { rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x1); diff --git a/drivers/media/i2c/rk628/rk628_mipi_dphy.h b/drivers/media/i2c/rk628/rk628_mipi_dphy.h index 8410f4d9d7df..72759eb1cea5 100644 --- a/drivers/media/i2c/rk628/rk628_mipi_dphy.h +++ b/drivers/media/i2c/rk628/rk628_mipi_dphy.h @@ -22,7 +22,6 @@ void rk628_testif_testclr_assert(struct rk628 *rk628, uint8_t mipi_id); u8 rk628_testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t mipi_id); u8 rk628_testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id); void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id); -void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mipi_id); int rk628_mipi_dphy_reset_assert(struct rk628 *rk628); int rk628_mipi_dphy_reset_deassert(struct rk628 *rk628); diff --git a/drivers/media/i2c/rk628/rk628_post_process.c b/drivers/media/i2c/rk628/rk628_post_process.c index 66bf979fa568..05db9ee6f6fc 100644 --- a/drivers/media/i2c/rk628/rk628_post_process.c +++ b/drivers/media/i2c/rk628/rk628_post_process.c @@ -1638,7 +1638,7 @@ static u8 rk628_get_output_color_space(struct rk628 *rk628, u8 input_color_space return rk628->tx_mode ? OPTM_CS_E_RGB : OPTM_CS_E_XV_YCC_709; case OPTM_CS_E_XV_YCC_2020: case OPTM_CS_E_RGB_2020: - return rk628->tx_mode ? OPTM_CS_E_RGB_2020 : OPTM_CS_E_XV_YCC_709; + return rk628->tx_mode ? OPTM_CS_E_RGB_2020 : OPTM_CS_E_XV_YCC_2020; case OPTM_CS_E_RGB_ADOBE: case OPTM_CS_E_YUV_ADOBE: return rk628->tx_mode ? OPTM_CS_E_RGB_ADOBE : OPTM_CS_E_XV_YCC_709; diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index bdebc322f0a1..4693ab164847 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -273,45 +273,13 @@ static const struct cif_output_fmt out_fmts[] = { .raw_bpp = 12, .csi_fmt_val = CSI_WRDDR_TYPE_RAW12, .fmt_type = CIF_FMT_TYPE_RAW, - }, { - .fourcc = V4L2_PIX_FMT_SBGGR16, - .cplanes = 1, - .mplanes = 1, - .bpp = { 16 }, - .raw_bpp = 16, - .csi_fmt_val = CSI_WRDDR_TYPE_RAW8, - .fmt_type = CIF_FMT_TYPE_RAW, - }, { - .fourcc = V4L2_PIX_FMT_SGBRG16, - .cplanes = 1, - .mplanes = 1, - .bpp = { 16 }, - .raw_bpp = 16, - .csi_fmt_val = CSI_WRDDR_TYPE_RAW8, - .fmt_type = CIF_FMT_TYPE_RAW, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG16, - .cplanes = 1, - .mplanes = 1, - .bpp = { 16 }, - .raw_bpp = 16, - .csi_fmt_val = CSI_WRDDR_TYPE_RAW8, - .fmt_type = CIF_FMT_TYPE_RAW, - }, { - .fourcc = V4L2_PIX_FMT_SRGGB16, - .cplanes = 1, - .mplanes = 1, - .bpp = { 16 }, - .raw_bpp = 16, - .csi_fmt_val = CSI_WRDDR_TYPE_RAW8, - .fmt_type = CIF_FMT_TYPE_RAW, }, { .fourcc = V4L2_PIX_FMT_Y16, .cplanes = 1, .mplanes = 1, .bpp = { 16 }, .raw_bpp = 16, - .csi_fmt_val = CSI_WRDDR_TYPE_RAW8, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW16, .fmt_type = CIF_FMT_TYPE_RAW, }, { .fourcc = V4L2_PIX_FMT_GREY, @@ -345,6 +313,13 @@ static const struct cif_output_fmt out_fmts[] = { .raw_bpp = 12, .csi_fmt_val = CSI_WRDDR_TYPE_RAW12, .fmt_type = CIF_FMT_TYPE_RAW, + }, { + .fourcc = V4L2_PIX_FMT_Y14, + .cplanes = 1, + .mplanes = 1, + .bpp = { 16 }, + .raw_bpp = 14, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588, }, { .fourcc = V4L2_PIX_FMT_Y10, .cplanes = 1, @@ -385,7 +360,39 @@ static const struct cif_output_fmt out_fmts[] = { .raw_bpp = 16, .csi_fmt_val = CSI_WRDDR_TYPE_RAW16, .fmt_type = CIF_FMT_TYPE_RAW, - } + }, { + .fourcc = V4L2_PIX_FMT_SBGGR14, + .cplanes = 1, + .mplanes = 1, + .bpp = { 16 }, + .raw_bpp = 14, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588, + .fmt_type = CIF_FMT_TYPE_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG14, + .cplanes = 1, + .mplanes = 1, + .bpp = { 16 }, + .raw_bpp = 14, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588, + .fmt_type = CIF_FMT_TYPE_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG14, + .cplanes = 1, + .mplanes = 1, + .bpp = { 16 }, + .raw_bpp = 14, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588, + .fmt_type = CIF_FMT_TYPE_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB14, + .cplanes = 1, + .mplanes = 1, + .bpp = { 16 }, + .raw_bpp = 14, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588, + .fmt_type = CIF_FMT_TYPE_RAW, + }, /* TODO: We can support NV12M/NV21M/NV16M/NV61M too */ }; @@ -572,6 +579,12 @@ static const struct cif_input_fmt in_fmts[] = { .csi_fmt_val = CSI_WRDDR_TYPE_RAW12, .fmt_type = CIF_FMT_TYPE_RAW, .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_Y14_1X14, + .dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_14, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, }, { .mbus_code = MEDIA_BUS_FMT_EBD_1X8, .dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_8, @@ -614,6 +627,26 @@ static const struct cif_input_fmt in_fmts[] = { .csi_fmt_val = CSI_WRDDR_TYPE_RAW16, .fmt_type = CIF_FMT_TYPE_RAW, .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SBGGR14_1X14, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SGBRG14_1X14, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SGRBG14_1X14, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SRGGB14_1X14, + .csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, }, }; @@ -789,6 +822,18 @@ static int rkcif_output_fmt_check(struct rkcif_stream *stream, if (output_fmt->fourcc == V4L2_PIX_FMT_NV12) ret = 0; break; + case MEDIA_BUS_FMT_SBGGR14_1X14: + case MEDIA_BUS_FMT_SGBRG14_1X14: + case MEDIA_BUS_FMT_SGRBG14_1X14: + case MEDIA_BUS_FMT_SRGGB14_1X14: + case MEDIA_BUS_FMT_Y14_1X14: + if (output_fmt->fourcc == V4L2_PIX_FMT_SRGGB14 || + output_fmt->fourcc == V4L2_PIX_FMT_SGRBG14 || + output_fmt->fourcc == V4L2_PIX_FMT_SGBRG14 || + output_fmt->fourcc == V4L2_PIX_FMT_SBGGR14 || + output_fmt->fourcc == V4L2_PIX_FMT_Y14) + ret = 0; + break; default: break; } @@ -915,6 +960,13 @@ static unsigned char get_data_type(u32 pixelformat, u8 cmd_mode_en, u8 dsi_input case MEDIA_BUS_FMT_SRGGB12_1X12: case MEDIA_BUS_FMT_Y12_1X12: return 0x2c; + /* csi raw14 */ + case MEDIA_BUS_FMT_SBGGR14_1X14: + case MEDIA_BUS_FMT_SGBRG14_1X14: + case MEDIA_BUS_FMT_SGRBG14_1X14: + case MEDIA_BUS_FMT_SRGGB14_1X14: + case MEDIA_BUS_FMT_Y14_1X14: + return 0x2d; /* csi raw16 */ case MEDIA_BUS_FMT_SBGGR16_1X16: case MEDIA_BUS_FMT_SGBRG16_1X16: @@ -2568,6 +2620,23 @@ out_get_buf: rkcif_write_register(dev, frm_addr_y, buff_addr_y); } } + if (buf_stream->is_force_update) { + if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || + mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) { + if (dev->chip_id < CHIP_RK3562_CIF) + rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_CTRL, 0x00010000); + else + rkcif_write_register_or(dev, get_reg_index_of_frm0_y_vlw(stream->id), BIT(31)); + } else { + if (dev->chip_id < CHIP_RK3562_CIF) + rkcif_write_register_or(dev, CIF_REG_DVP_CTRL, 0x00010000); + else if (dev->chip_id < CHIP_RK3576_CIF) + rkcif_write_register_or(dev, CIF_REG_DVP_VIR_LINE_WIDTH, BIT(28) << stream->id); + else + rkcif_write_register_or(dev, CIF_REG_DVP_VIR_LINE_WIDTH, BIT(31)); + } + buf_stream->is_force_update = false; + } spin_unlock_irqrestore(&buf_stream->vbq_lock, flags); return 0; } @@ -2584,6 +2653,19 @@ static int rkcif_assign_new_buffer_pingpong_toisp(struct rkcif_stream *stream, return ret; } +static void rkcif_check_force_update_buf(struct rkcif_stream *stream) +{ + u64 cur_time = 0; + u64 offset = 0; + + offset = stream->cifdev->readout_ns - 2000000; + cur_time = rkcif_time_get_ns(stream->cifdev); + if (stream->dma_en && + (cur_time - stream->readout.fs_timestamp) > offset && + !stream->is_in_vblank) + stream->is_force_update = true; +} + void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) { struct rkcif_device *dev = stream->cifdev; @@ -2634,6 +2716,11 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) buf_stream->toisp_buf_state.check_cnt == 0) is_dual_update = true; + if ((buf_stream->toisp_buf_state.state == RKCIF_TOISP_BUF_LOSS || + buf_stream->toisp_buf_state.state == RKCIF_TOISP_BUF_THESAME) && + buf_stream->toisp_buf_state.check_cnt == 0) + rkcif_check_force_update_buf(buf_stream); + if ((dev->rdbk_debug > 2 && stream->frame_idx < 15) || rkcif_debug > 4) @@ -3996,6 +4083,7 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, const struct cif_output_fmt *fmt; u32 fourcc; int vc = dev->channels[stream->id].vc; + u32 raw_bpp = 0; channel->enable = 1; channel->width = stream->pixm.width; @@ -4061,11 +4149,20 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, if (fmt->fmt_type == CIF_FMT_TYPE_RAW && stream->is_compact && fmt->csi_fmt_val != CSI_WRDDR_TYPE_RGB888 && fmt->csi_fmt_val != CSI_WRDDR_TYPE_RGB565) { + if (dev->chip_id < CHIP_RV1126B_CIF && + (fmt->fourcc == V4L2_PIX_FMT_Y14 || + fmt->fourcc == V4L2_PIX_FMT_SBGGR14 || + fmt->fourcc == V4L2_PIX_FMT_SGBRG14 || + fmt->fourcc == V4L2_PIX_FMT_SGRBG14 || + fmt->fourcc == V4L2_PIX_FMT_SRGGB14)) + raw_bpp = 12; + else + raw_bpp = fmt->raw_bpp; if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { - channel->virtual_width = ALIGN(channel->width * 2 * fmt->raw_bpp / 8, 256); - channel->left_virtual_width = channel->width * fmt->raw_bpp / 8; + channel->virtual_width = ALIGN(channel->width * 2 * raw_bpp / 8, 256); + channel->left_virtual_width = channel->width * raw_bpp / 8; } else { - channel->virtual_width = ALIGN(channel->width * fmt->raw_bpp / 8, 256); + channel->virtual_width = ALIGN(channel->width * raw_bpp / 8, 256); } } else { if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { @@ -4418,9 +4515,14 @@ static int rkcif_csi_get_output_type_mask(struct rkcif_stream *stream) case V4L2_PIX_FMT_SGRBG12: case V4L2_PIX_FMT_SGBRG12: case V4L2_PIX_FMT_SBGGR12: + case V4L2_PIX_FMT_SRGGB14: + case V4L2_PIX_FMT_SGRBG14: + case V4L2_PIX_FMT_SGBRG14: + case V4L2_PIX_FMT_SBGGR14: case V4L2_PIX_FMT_GREY: case V4L2_PIX_FMT_Y10: case V4L2_PIX_FMT_Y12: + case V4L2_PIX_FMT_Y14: if (stream->is_compact) mask = CSI_WRDDR_TYPE_RAW_COMPACT; else @@ -4488,9 +4590,14 @@ static int rkcif_csi_get_output_type_mask_rk3576(struct rkcif_stream *stream) case V4L2_PIX_FMT_SGRBG12: case V4L2_PIX_FMT_SGBRG12: case V4L2_PIX_FMT_SBGGR12: + case V4L2_PIX_FMT_SRGGB14: + case V4L2_PIX_FMT_SGRBG14: + case V4L2_PIX_FMT_SGBRG14: + case V4L2_PIX_FMT_SBGGR14: case V4L2_PIX_FMT_GREY: case V4L2_PIX_FMT_Y10: case V4L2_PIX_FMT_Y12: + case V4L2_PIX_FMT_Y14: if (stream->is_compact) mask = CSI_WRDDR_TYPE_RAW_COMPACT << 3; else @@ -5394,19 +5501,24 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode } if (stream->cifdev->chip_id < CHIP_RK3588_CIF) { rkcif_csi_channel_set(stream, channel, mbus_type); - } else if (stream->cifdev->chip_id < CHIP_RV1126B_CIF) { + } else { if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { for (i = 0; i < channel->capture_info.multi_dev.dev_num; i++) { dev->csi_host_idx = channel->capture_info.multi_dev.dev_idx[i]; - rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode, i); + if (stream->cifdev->chip_id < CHIP_RV1126B_CIF) + rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode, i); + else + rkcif_csi_channel_set_rv1126b(stream, channel, mbus_type, mode, i); } } else { if (!dev->switch_info.is_use_switch || - atomic_inc_return(&dev->hw_dev->switch_stream_cnt[dev->switch_info.host_idx]) == 1) - rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode, 0); + atomic_inc_return(&dev->hw_dev->switch_stream_cnt[dev->switch_info.host_idx]) == 1) { + if (stream->cifdev->chip_id < CHIP_RV1126B_CIF) + rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode, 0); + else + rkcif_csi_channel_set_rv1126b(stream, channel, mbus_type, mode, 0); + } } - } else { - rkcif_csi_channel_set_rv1126b(stream, channel, mbus_type, mode, 0); } } else { if (stream->cifdev->chip_id >= CHIP_RK3588_CIF) { @@ -6982,6 +7094,7 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, stream->crop_mask = 0; stream->frame_loss = 0; stream->is_fb_first_frame = true; + stream->is_force_update = false; } if (mode == RKCIF_STREAM_MODE_CAPTURE) { tasklet_disable(&stream->vb_done_tasklet); @@ -7316,6 +7429,11 @@ static u32 rkcif_align_bits_per_pixel(struct rkcif_stream *stream, case V4l2_PIX_FMT_EBD8: case V4L2_PIX_FMT_Y10: case V4L2_PIX_FMT_Y12: + case V4L2_PIX_FMT_Y14: + case V4L2_PIX_FMT_SRGGB14: + case V4L2_PIX_FMT_SGRBG14: + case V4L2_PIX_FMT_SGBRG14: + case V4L2_PIX_FMT_SBGGR14: if (stream->cifdev->chip_id < CHIP_RV1126_CIF) { bpp = max(fmt->bpp[plane_index], (u8)CIF_RAW_STORED_BIT_WIDTH); cal = CIF_RAW_STORED_BIT_WIDTH; @@ -7620,9 +7738,14 @@ static int rkcif_dvp_get_output_type_mask(struct rkcif_stream *stream) case V4L2_PIX_FMT_SGRBG12: case V4L2_PIX_FMT_SGBRG12: case V4L2_PIX_FMT_SBGGR12: + case V4L2_PIX_FMT_SRGGB14: + case V4L2_PIX_FMT_SGRBG14: + case V4L2_PIX_FMT_SGBRG14: + case V4L2_PIX_FMT_SBGGR14: case V4L2_PIX_FMT_GREY: case V4L2_PIX_FMT_Y10: case V4L2_PIX_FMT_Y12: + case V4L2_PIX_FMT_Y14: if (stream->is_compact) mask = CSI_WRDDR_TYPE_RAW_COMPACT << 11; else @@ -7701,6 +7824,11 @@ static int rkcif_dvp_get_output_type_mask_rk3576(struct rkcif_stream *stream) case V4L2_PIX_FMT_GREY: case V4L2_PIX_FMT_Y10: case V4L2_PIX_FMT_Y12: + case V4L2_PIX_FMT_Y14: + case V4L2_PIX_FMT_SRGGB14: + case V4L2_PIX_FMT_SGRBG14: + case V4L2_PIX_FMT_SGBRG14: + case V4L2_PIX_FMT_SBGGR14: if (stream->is_compact) mask = CSI_WRDDR_TYPE_RAW_COMPACT << 15; else @@ -8601,6 +8729,8 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, enum rkcif_stream_mode mo tasklet_enable(&stream->vb_done_tasklet); if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) { + dev->sensor_linetime = rkcif_get_linetime(stream); + dev->readout_ns = dev->terminal_sensor.raw_rect.height * dev->sensor_linetime; ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true); if (ret < 0) { v4l2_err(v4l2_dev, "open cif pipeline failed %d\n", @@ -8823,6 +8953,7 @@ int rkcif_set_fmt(struct rkcif_stream *stream, struct rkcif_extend_info *extend_line = &stream->extend_line; struct csi_channel_info *channel_info = &dev->channels[stream->id]; int ret; + u32 raw_bpp = 0; for (i = 0; i < RKCIF_MAX_PLANE; i++) memset(&pixm->plane_fmt[i], 0, sizeof(struct v4l2_plane_pix_format)); @@ -8938,13 +9069,31 @@ int rkcif_set_fmt(struct rkcif_stream *stream, dev->active_sensor->mbus.type == V4L2_MBUS_CCP2) && fmt->csi_fmt_val != CSI_WRDDR_TYPE_RGB888 && fmt->csi_fmt_val != CSI_WRDDR_TYPE_RGB565) { - bpl = ALIGN(width * fmt->raw_bpp / 8, 256); + if (dev->chip_id < CHIP_RV1126B_CIF && + (fmt->fourcc == V4L2_PIX_FMT_Y14 || + fmt->fourcc == V4L2_PIX_FMT_SBGGR14 || + fmt->fourcc == V4L2_PIX_FMT_SGBRG14 || + fmt->fourcc == V4L2_PIX_FMT_SGRBG14 || + fmt->fourcc == V4L2_PIX_FMT_SRGGB14)) + raw_bpp = 12; + else + raw_bpp = fmt->raw_bpp; + bpl = ALIGN(width * raw_bpp / 8, 256); } else { if (fmt->fmt_type == CIF_FMT_TYPE_RAW && stream->is_compact && fmt->csi_fmt_val != CSI_WRDDR_TYPE_RGB888 && fmt->csi_fmt_val != CSI_WRDDR_TYPE_RGB565 && dev->chip_id >= CHIP_RK3588_CIF) { - bpl = ALIGN(width * fmt->raw_bpp / 8, 256); + if (dev->chip_id < CHIP_RV1126B_CIF && + (fmt->fourcc == V4L2_PIX_FMT_Y14 || + fmt->fourcc == V4L2_PIX_FMT_SBGGR14 || + fmt->fourcc == V4L2_PIX_FMT_SGBRG14 || + fmt->fourcc == V4L2_PIX_FMT_SGRBG14 || + fmt->fourcc == V4L2_PIX_FMT_SRGGB14)) + raw_bpp = 12; + else + raw_bpp = fmt->raw_bpp; + bpl = ALIGN(width * raw_bpp / 8, 256); } else { bpp = rkcif_align_bits_per_pixel(stream, fmt, i); bpl = ALIGN(width * bpp / CIF_YUV_STORED_BIT_WIDTH, 8); @@ -9095,6 +9244,7 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id) memset(&stream->sensor_exp_info, 0, sizeof(stream->sensor_exp_info)); stream->frame_loss = 0; stream->is_pause_stream = false; + stream->is_force_update = false; } int rkcif_sensor_set_power(struct rkcif_stream *stream, int on) @@ -13088,6 +13238,21 @@ u32 rkcif_mbus_pixelcode_to_v4l2(u32 pixelcode) case MEDIA_BUS_FMT_SRGGB16_1X16: pixelformat = V4L2_PIX_FMT_SRGGB16; break; + case MEDIA_BUS_FMT_Y14_1X14: + pixelformat = V4L2_PIX_FMT_Y14; + break; + case MEDIA_BUS_FMT_SBGGR14_1X14: + pixelformat = V4L2_PIX_FMT_SBGGR14; + break; + case MEDIA_BUS_FMT_SGBRG14_1X14: + pixelformat = V4L2_PIX_FMT_SGBRG14; + break; + case MEDIA_BUS_FMT_SGRBG14_1X14: + pixelformat = V4L2_PIX_FMT_SGRBG14; + break; + case MEDIA_BUS_FMT_SRGGB14_1X14: + pixelformat = V4L2_PIX_FMT_SRGGB14; + break; default: pixelformat = V4L2_PIX_FMT_SRGGB10; } @@ -13179,8 +13344,10 @@ void rkcif_enable_dma_capture(struct rkcif_stream *stream, bool is_only_enable) } else { if (cif_dev->chip_id < CHIP_RK3562_CIF) rkcif_write_register_or(cif_dev, CIF_REG_DVP_CTRL, 0x00010000); - else + else if (cif_dev->chip_id < CHIP_RK3576_CIF) rkcif_write_register_or(cif_dev, CIF_REG_DVP_VIR_LINE_WIDTH, BIT(28) << stream->id); + else + rkcif_write_register_or(cif_dev, CIF_REG_DVP_VIR_LINE_WIDTH, BIT(31)); } if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) { diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index c3dbe068391e..1a54a894203b 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -680,6 +680,7 @@ struct rkcif_stream { bool is_m_online_fb_res; bool is_fb_first_frame; bool is_pause_stream; + bool is_force_update; }; struct rkcif_lvds_subdev { @@ -1057,6 +1058,7 @@ struct rkcif_device { u32 early_line; int isp_runtime_max; int sensor_linetime; + u64 readout_ns; u32 err_state; struct rkcif_err_state_work err_state_work; struct rkcif_sensor_work sensor_work; diff --git a/drivers/media/platform/rockchip/cif/regs.h b/drivers/media/platform/rockchip/cif/regs.h index eea73b3ced40..755898a5f7de 100644 --- a/drivers/media/platform/rockchip/cif/regs.h +++ b/drivers/media/platform/rockchip/cif/regs.h @@ -874,6 +874,7 @@ enum cif_reg_index { #define RAW_DATA_WIDTH_8 (0x00 << 11) #define RAW_DATA_WIDTH_10 (0x01 << 11) #define RAW_DATA_WIDTH_12 (0x02 << 11) +#define RAW_DATA_WIDTH_14 (0x03 << 11) #define MIPI_MODE_32BITS_BYPASS (0x00 << 13) #define MIPI_MODE_RGB (0x01 << 13) #define MIPI_MODE_YUV (0x02 << 13) diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index cad599f5831e..ff16cc6452f8 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -208,6 +208,27 @@ static int sditf_get_set_fmt(struct v4l2_subdev *sd, priv->cap_info.offset_x = 0; priv->cap_info .offset_y = 0; } + if (cif_dev->chip_id < CHIP_RV1126B_CIF) { + switch (fmt->format.code) { + case MEDIA_BUS_FMT_Y14_1X14: + fmt->format.code = MEDIA_BUS_FMT_Y12_1X12; + break; + case MEDIA_BUS_FMT_SBGGR14_1X14: + fmt->format.code = MEDIA_BUS_FMT_SBGGR12_1X12; + break; + case MEDIA_BUS_FMT_SGBRG14_1X14: + fmt->format.code = MEDIA_BUS_FMT_SGBRG12_1X12; + break; + case MEDIA_BUS_FMT_SGRBG14_1X14: + fmt->format.code = MEDIA_BUS_FMT_SGRBG12_1X12; + break; + case MEDIA_BUS_FMT_SRGGB14_1X14: + fmt->format.code = MEDIA_BUS_FMT_SRGGB12_1X12; + break; + default: + break; + } + } priv->cap_info.width = fmt->format.width; priv->cap_info.height = fmt->format.height; pixm.pixelformat = rkcif_mbus_pixelcode_to_v4l2(fmt->format.code); diff --git a/drivers/media/platform/rockchip/isp/csi.c b/drivers/media/platform/rockchip/isp/csi.c index 8a7cc961485a..74d1ba06e44e 100644 --- a/drivers/media/platform/rockchip/isp/csi.c +++ b/drivers/media/platform/rockchip/isp/csi.c @@ -644,6 +644,8 @@ int rkisp_csi_config_patch(struct rkisp_device *dev, bool is_pre_cfg) } else { rkisp_unite_write(dev, CSI2RX_CTRL0, SW_IBUF_OP_MODE(dev->hdr.op_mode), false); + rkisp_unite_write(dev, CSI2RX_DATA_IDS_1, + dev->isp_sdev.in_fmt.mipi_dt, false); } /* hdr merge */ switch (dev->hdr.op_mode) { diff --git a/drivers/media/platform/rockchip/isp/dmarx.c b/drivers/media/platform/rockchip/isp/dmarx.c index 40df35dda320..8e489f4a5ff5 100644 --- a/drivers/media/platform/rockchip/isp/dmarx.c +++ b/drivers/media/platform/rockchip/isp/dmarx.c @@ -196,6 +196,26 @@ static const struct capture_fmt rawrd_fmts[] = { .fmt_type = FMT_YUV, .bpp = { 16 }, .mplanes = 1, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB14, + .fmt_type = FMT_BAYER, + .bpp = { 14 }, + .mplanes = 1, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG14, + .fmt_type = FMT_BAYER, + .bpp = { 14 }, + .mplanes = 1, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG14, + .fmt_type = FMT_BAYER, + .bpp = { 14 }, + .mplanes = 1, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR14, + .fmt_type = FMT_BAYER, + .bpp = { 14 }, + .mplanes = 1, }, { .fourcc = V4L2_PIX_FMT_SRGGB16, .fmt_type = FMT_BAYER, @@ -216,6 +236,11 @@ static const struct capture_fmt rawrd_fmts[] = { .fmt_type = FMT_BAYER, .bpp = { 16 }, .mplanes = 1, + }, { + .fourcc = V4L2_PIX_FMT_Y14, + .fmt_type = FMT_BAYER, + .bpp = { 14 }, + .mplanes = 1, }, { .fourcc = V4L2_PIX_FMT_Y16, .fmt_type = FMT_BAYER, @@ -367,6 +392,13 @@ static int rawrd_config_mi(struct rkisp_stream *stream) case V4L2_PIX_FMT_VYUY: val |= CIF_CSI2_DT_YUV422_8b; break; + case V4L2_PIX_FMT_SRGGB14: + case V4L2_PIX_FMT_SBGGR14: + case V4L2_PIX_FMT_SGRBG14: + case V4L2_PIX_FMT_SGBRG14: + case V4L2_PIX_FMT_Y14: + val |= CIF_CSI2_DT_RAW14; + break; case V4L2_PIX_FMT_SRGGB16: case V4L2_PIX_FMT_SBGGR16: case V4L2_PIX_FMT_SGRBG16: @@ -816,6 +848,26 @@ static int rkisp_set_fmt(struct rkisp_stream *stream, u32 xsubs = 1, ysubs = 1; unsigned int i; + if (stream->ispdev->isp_ver < ISP_V35 && + (pixm->pixelformat == V4L2_PIX_FMT_SBGGR14 || + pixm->pixelformat == V4L2_PIX_FMT_SGBRG14 || + pixm->pixelformat == V4L2_PIX_FMT_SGRBG14 || + pixm->pixelformat == V4L2_PIX_FMT_SRGGB14 || + pixm->pixelformat == V4L2_PIX_FMT_Y14)) { + if (pixm->pixelformat == V4L2_PIX_FMT_SBGGR14) + pixm->pixelformat = V4L2_PIX_FMT_SBGGR12; + else if (pixm->pixelformat == V4L2_PIX_FMT_SGBRG14) + pixm->pixelformat = V4L2_PIX_FMT_SGBRG12; + else if (pixm->pixelformat == V4L2_PIX_FMT_SGRBG14) + pixm->pixelformat = V4L2_PIX_FMT_SGRBG12; + else if (pixm->pixelformat == V4L2_PIX_FMT_SRGGB14) + pixm->pixelformat = V4L2_PIX_FMT_SRGGB12; + else + pixm->pixelformat = V4L2_PIX_FMT_Y12; + v4l2_warn(&stream->ispdev->v4l2_dev, + "no support raw14, rawrd format force to raw12\n"); + } + fmt = find_fmt(stream, pixm->pixelformat); if (!fmt) { v4l2_err(&stream->ispdev->v4l2_dev, diff --git a/drivers/media/platform/rockchip/isp/regs.h b/drivers/media/platform/rockchip/isp/regs.h index 79b6e89b9b23..6a378152535b 100644 --- a/drivers/media/platform/rockchip/isp/regs.h +++ b/drivers/media/platform/rockchip/isp/regs.h @@ -406,6 +406,7 @@ #define CIF_CSI2_DT_RAW8 0x2A #define CIF_CSI2_DT_RAW10 0x2B #define CIF_CSI2_DT_RAW12 0x2C +#define CIF_CSI2_DT_RAW14 0x2D #define CIF_CSI2_DT_RAW16 0x2e #define CIF_CSI2_DT_SPD 0x2F diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 25f32da33b6f..9ed7eb162de7 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -2787,6 +2787,41 @@ static const struct ispsd_in_fmt rkisp_isp_input_formats[] = { .mipi_dt = CIF_CSI2_DT_RAW12, .yuv_seq = CIF_ISP_ACQ_PROP_YCBYCR, .bus_width = 12, + }, { + .name = "Y14_1X14", + .mbus_code = MEDIA_BUS_FMT_Y14_1X14, + .fmt_type = FMT_BAYER, + .mipi_dt = CIF_CSI2_DT_RAW14, + .yuv_seq = CIF_ISP_ACQ_PROP_YCBYCR, + .bus_width = 14, + }, { + .name = "SRGGB14_1X14", + .mbus_code = MEDIA_BUS_FMT_SRGGB14_1X14, + .fmt_type = FMT_BAYER, + .mipi_dt = CIF_CSI2_DT_RAW14, + .bayer_pat = RAW_RGGB, + .bus_width = 14, + }, { + .name = "SBGGR14_1X14", + .mbus_code = MEDIA_BUS_FMT_SBGGR14_1X14, + .fmt_type = FMT_BAYER, + .mipi_dt = CIF_CSI2_DT_RAW14, + .bayer_pat = RAW_BGGR, + .bus_width = 14, + }, { + .name = "SGBRG14_1X14", + .mbus_code = MEDIA_BUS_FMT_SGBRG14_1X14, + .fmt_type = FMT_BAYER, + .mipi_dt = CIF_CSI2_DT_RAW14, + .bayer_pat = RAW_GBRG, + .bus_width = 14, + }, { + .name = "SGRBG14_1X14", + .mbus_code = MEDIA_BUS_FMT_SGRBG14_1X14, + .fmt_type = FMT_BAYER, + .mipi_dt = CIF_CSI2_DT_RAW14, + .bayer_pat = RAW_GRBG, + .bus_width = 14, }, { .name = "SRGGB16_1X16", .mbus_code = MEDIA_BUS_FMT_SRGGB16_1X16, @@ -2795,21 +2830,21 @@ static const struct ispsd_in_fmt rkisp_isp_input_formats[] = { .bayer_pat = RAW_RGGB, .bus_width = 16, }, { - .name = "SBGGR12_1X16", + .name = "SBGGR16_1X16", .mbus_code = MEDIA_BUS_FMT_SBGGR16_1X16, .fmt_type = FMT_BAYER, .mipi_dt = CIF_CSI2_DT_RAW16, .bayer_pat = RAW_BGGR, .bus_width = 16, }, { - .name = "SGBRG12_1X16", + .name = "SGBRG16_1X16", .mbus_code = MEDIA_BUS_FMT_SGBRG16_1X16, .fmt_type = FMT_BAYER, .mipi_dt = CIF_CSI2_DT_RAW16, .bayer_pat = RAW_GBRG, .bus_width = 16, }, { - .name = "SGRBG12_1X16", + .name = "SGRBG16_1X16", .mbus_code = MEDIA_BUS_FMT_SGRBG16_1X16, .fmt_type = FMT_BAYER, .mipi_dt = CIF_CSI2_DT_RAW16, @@ -2974,6 +3009,25 @@ static int rkisp_isp_sd_set_fmt(struct v4l2_subdev *sd, struct v4l2_pix_format_mplane pixm = { 0 }; const struct ispsd_in_fmt *in_fmt; + if (isp_dev->isp_ver < ISP_V35 && + (mf->code == MEDIA_BUS_FMT_SGRBG14_1X14 || + mf->code == MEDIA_BUS_FMT_SGBRG14_1X14 || + mf->code == MEDIA_BUS_FMT_SBGGR14_1X14 || + mf->code == MEDIA_BUS_FMT_SRGGB14_1X14 || + mf->code == MEDIA_BUS_FMT_Y14_1X14)) { + if (mf->code == MEDIA_BUS_FMT_SGRBG14_1X14) + mf->code = MEDIA_BUS_FMT_SGRBG12_1X12; + else if (mf->code == MEDIA_BUS_FMT_SGBRG14_1X14) + mf->code = MEDIA_BUS_FMT_SGBRG12_1X12; + else if (mf->code == MEDIA_BUS_FMT_SBGGR12_1X12) + mf->code = MEDIA_BUS_FMT_SBGGR12_1X12; + else if (mf->code == MEDIA_BUS_FMT_SRGGB14_1X14) + mf->code = MEDIA_BUS_FMT_SRGGB12_1X12; + else + mf->code = MEDIA_BUS_FMT_Y12_1X12; + v4l2_warn(&isp_dev->v4l2_dev, + "no support raw14, isp format force to raw12\n"); + } in_fmt = find_in_fmt(mf->code); if (!in_fmt || mf->width < CIF_ISP_INPUT_W_MIN || diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h index 295974d9bc89..43c595b70e52 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h @@ -128,6 +128,7 @@ struct csi2_dphy_hw { int dphy_dev_num; enum csi2_dphy_lane_mode lane_mode; struct resource *res; + int hw_idx; int (*stream_on)(struct csi2_dphy *dphy, struct v4l2_subdev *sd); int (*stream_off)(struct csi2_dphy *dphy, struct v4l2_subdev *sd); diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c index 4e96b19ac333..47ac3ce72124 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c @@ -650,6 +650,40 @@ static unsigned char get_lvds_data_width(u32 pixelformat) } } +static unsigned char get_lvds_data_width_rv1126b(u32 pixelformat) +{ + switch (pixelformat) { + /* csi raw8 */ + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SGBRG8_1X8: + case MEDIA_BUS_FMT_SGRBG8_1X8: + case MEDIA_BUS_FMT_SRGGB8_1X8: + return 0x1; + /* csi raw10 */ + case MEDIA_BUS_FMT_SBGGR10_1X10: + case MEDIA_BUS_FMT_SGBRG10_1X10: + case MEDIA_BUS_FMT_SGRBG10_1X10: + case MEDIA_BUS_FMT_SRGGB10_1X10: + return 0x2; + /* csi raw12 */ + case MEDIA_BUS_FMT_SBGGR12_1X12: + case MEDIA_BUS_FMT_SGBRG12_1X12: + case MEDIA_BUS_FMT_SGRBG12_1X12: + case MEDIA_BUS_FMT_SRGGB12_1X12: + return 0x3; + /* csi uyvy 422 */ + case MEDIA_BUS_FMT_UYVY8_2X8: + case MEDIA_BUS_FMT_VYUY8_2X8: + case MEDIA_BUS_FMT_YUYV8_2X8: + case MEDIA_BUS_FMT_YVYU8_2X8: + case MEDIA_BUS_FMT_RGB888_1X24: + return 0x1; + + default: + return 0x2; + } +} + static void csi2_dphy_hw_do_reset(struct csi2_dphy_hw *hw) { if (hw->rsts_bulk) @@ -678,7 +712,7 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, if (hw->lane_mode == LANE_MODE_FULL) { val = !GRF_CSI2PHY_LANE_SEL_SPLIT; - if (dphy->phy_index < 3) { + if (hw->hw_idx == 0) { write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN, GENMASK(sensor->lanes - 1, 0)); write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); @@ -991,7 +1025,10 @@ static int csi2_dphy_hw_stream_on(struct csi2_dphy *dphy, write_csi2_dphy_reg(hw, CSI2PHY_PATH0_MODEL, 0x2); } else { write_csi2_dphy_reg(hw, CSI2PHY_PATH0_MODEL, 0x4); - lvds_width = get_lvds_data_width(sensor->format.code); + if (hw->drv_data->chip_id == CHIP_ID_RV1126B) + lvds_width = get_lvds_data_width_rv1126b(sensor->format.code); + else + lvds_width = get_lvds_data_width(sensor->format.code); write_csi2_dphy_reg(hw, CSI2PHY_PATH0_LVDS_MODEL, (lvds_width << 4) | 0X0f); } } else { @@ -999,7 +1036,10 @@ static int csi2_dphy_hw_stream_on(struct csi2_dphy *dphy, write_csi2_dphy_reg(hw, CSI2PHY_PATH1_MODEL, 0x2); } else { write_csi2_dphy_reg(hw, CSI2PHY_PATH1_MODEL, 0x4); - lvds_width = get_lvds_data_width(sensor->format.code); + if (hw->drv_data->chip_id == CHIP_ID_RV1126B) + lvds_width = get_lvds_data_width_rv1126b(sensor->format.code); + else + lvds_width = get_lvds_data_width(sensor->format.code); write_csi2_dphy_reg(hw, CSI2PHY_PATH1_LVDS_MODEL, (lvds_width << 4) | 0X0f); } } diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c index 9bbf7f5d1a3b..418405ed4bc0 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c @@ -1161,6 +1161,7 @@ static int rockchip_csi2_dphy_get_inno_phy_hw(struct csi2_dphy *dphy) dphy->phy_index); return -EINVAL; } + dphy_hw->hw_idx = i; dphy->dphy_hw_group[i] = dphy_hw; } return 0; diff --git a/drivers/regulator/rk806-regulator.c b/drivers/regulator/rk806-regulator.c index 2672bf91dd77..3eba9d6e7957 100644 --- a/drivers/regulator/rk806-regulator.c +++ b/drivers/regulator/rk806-regulator.c @@ -1195,6 +1195,20 @@ static int __maybe_unused rk806_suspend(struct device *dev) for (i = RK806_ID_DCDC1; i < RK806_ID_END; i++) rk806_field_write(rk806, BUCK1_VSEL_CTR_SEL + i, CTR_BY_PWRCTRL1); } else { + for (i = RK806_ID_DCDC1; i < RK806_ID_END; i++) { + if (pdata->dvs_control_suspend[i] == CTR_BY_PWRCTRL1) { + chip_ver = rk806_field_read(rk806, CHIP_VER); + if (chip_ver & 0x08) + rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_SLP_FUN); + else + rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_DVS_FUN); + } + if (pdata->dvs_control_suspend[i] == CTR_BY_PWRCTRL2) + rk806_field_write(rk806, PWRCTRL2_FUN, PWRCTRL_DVS_FUN); + if (pdata->dvs_control_suspend[i] == CTR_BY_PWRCTRL3) + rk806_field_write(rk806, PWRCTRL3_FUN, PWRCTRL_DVS_FUN); + } + for (i = 0; i <= RK806_ID_PLDO6 - RK806_ID_PLDO1; i++) { value = rk806_field_read(rk806, PLDO1_ON_VSEL + i); rk806_field_write(rk806, PLDO1_SLP_VSEL + i, value); @@ -1209,18 +1223,6 @@ static int __maybe_unused rk806_suspend(struct device *dev) rk806_field_write(rk806, PLDO4_VSEL_CTR_SEL, pdata->dvs_control_suspend[RK806_ID_PLDO3]); rk806_field_write(rk806, PLDO5_VSEL_CTR_SEL, pdata->dvs_control_suspend[RK806_ID_PLDO4]); rk806_field_write(rk806, PLDO6_VSEL_CTR_SEL, pdata->dvs_control_suspend[RK806_ID_PLDO5]); - - for (i = RK806_ID_DCDC1; i < RK806_ID_END; i++) { - if (pdata->dvs_control_suspend[i] == CTR_BY_PWRCTRL2) - rk806_field_write(rk806, PWRCTRL2_FUN, PWRCTRL_DVS_FUN); - if (pdata->dvs_control_suspend[i] == CTR_BY_PWRCTRL3) - rk806_field_write(rk806, PWRCTRL3_FUN, PWRCTRL_DVS_FUN); - } - chip_ver = rk806_field_read(rk806, CHIP_VER); - if (chip_ver & 0x08) - rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_SLP_FUN); - else - rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_DVS_FUN); } return 0; diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 373eee1e6dc3..a53b5c21c5aa 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -70,6 +70,7 @@ enum adc_sort_mode { struct phy_config { unsigned int bias; + unsigned int offset; }; /** @@ -337,6 +338,7 @@ struct rockchip_thermal_data { #define RV1126B_GRF_TSADC_CON0 0x50 #define RV1126B_GRF_TSADC_CON1 0x54 +#define RV1126B_GRF_TSADC_CON4 0x60 #define RV1126B_GRF_TSADC_CON6 0x68 #define RV1126B_GRF_TSADC_ST1 0x114 #define RV1126B_UNLOCK_VALUE 0xa5 @@ -345,6 +347,8 @@ struct rockchip_thermal_data { #define RV1126B_UNLOCK_TRIGGER_MASK (BIT(8) << 16) #define RV1126B_MAX_BIAS 0x7f #define RV1126B_BIAS_MASK (0x7f << 16) +#define RV1126B_MAX_OFFSET 0xffff +#define RV1126B_OFFSET_MASK (0xffff << 16) #define RV1126B_CTRL_MASK (0x8078 << 16) #define GRF_SARADC_TESTBIT_ON (0x10001 << 2) @@ -1719,8 +1723,16 @@ static void rv1126b_tsadc_phy_init(struct device *dev, struct regmap *grf, regmap_write(grf, RV1126B_GRF_TSADC_CON6, phy_cfg->bias | RV1126B_BIAS_MASK); } + if (!phy_cfg->offset) { + regmap_read(grf, RV1126B_GRF_TSADC_CON4, &val); + phy_cfg->offset = val & RV1126B_MAX_OFFSET; + } else { + regmap_write(grf, RV1126B_GRF_TSADC_CON4, + phy_cfg->offset | RV1126B_OFFSET_MASK); + } regmap_read(grf, RV1126B_GRF_TSADC_ST1, &val); - dev_info(dev, "width=0x%x, bias=0x%x\n", val, phy_cfg->bias); + dev_info(dev, "width=0x%x, bias=0x%x, offset=0x%x\n", val, phy_cfg->bias, + phy_cfg->offset); regmap_write(grf, RV1126B_GRF_TSADC_CON0, RV1126B_CTRL_MASK); regmap_write(grf, RV1126B_GRF_TSADC_CON1, RV1126B_UNLOCK_VALUE | RV1126B_UNLOCK_VALUE_MASK);