| .. | .. |
|---|
| 20 | 20 | #include <media/videobuf2-dma-contig.h> |
|---|
| 21 | 21 | #include <media/v4l2-fwnode.h> |
|---|
| 22 | 22 | #include <linux/iommu.h> |
|---|
| 23 | | -#include <dt-bindings/soc/rockchip-system-status.h> |
|---|
| 24 | 23 | #include <soc/rockchip/rockchip-system-status.h> |
|---|
| 25 | 24 | #include <linux/io.h> |
|---|
| 26 | 25 | #include <linux/mfd/syscon.h> |
|---|
| .. | .. |
|---|
| 644 | 643 | } |
|---|
| 645 | 644 | } |
|---|
| 646 | 645 | if (index < CIF_REG_INDEX_MAX) { |
|---|
| 647 | | - if (index == CIF_REG_DVP_CTRL || reg->offset != 0x0) |
|---|
| 646 | + if (index == CIF_REG_DVP_CTRL || reg->offset != 0x0) { |
|---|
| 648 | 647 | write_cif_reg(base, reg->offset + csi_offset, val); |
|---|
| 649 | | - else |
|---|
| 648 | + v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, |
|---|
| 649 | + "write reg[0x%x]:0x%x!!!\n", |
|---|
| 650 | + reg->offset + csi_offset, val); |
|---|
| 651 | + } else { |
|---|
| 650 | 652 | v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, |
|---|
| 651 | 653 | "write reg[%d]:0x%x failed, maybe useless!!!\n", |
|---|
| 652 | 654 | index, val); |
|---|
| 655 | + } |
|---|
| 653 | 656 | } |
|---|
| 654 | 657 | } |
|---|
| 655 | 658 | |
|---|
| .. | .. |
|---|
| 681 | 684 | reg_val = read_cif_reg(base, reg->offset + csi_offset); |
|---|
| 682 | 685 | reg_val |= val; |
|---|
| 683 | 686 | write_cif_reg(base, reg->offset + csi_offset, reg_val); |
|---|
| 687 | + v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, |
|---|
| 688 | + "write or reg[0x%x]:0x%x!!!\n", |
|---|
| 689 | + reg->offset + csi_offset, val); |
|---|
| 684 | 690 | } else { |
|---|
| 685 | 691 | v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, |
|---|
| 686 | 692 | "write reg[%d]:0x%x with OR failed, maybe useless!!!\n", |
|---|
| .. | .. |
|---|
| 717 | 723 | reg_val = read_cif_reg(base, reg->offset + csi_offset); |
|---|
| 718 | 724 | reg_val &= val; |
|---|
| 719 | 725 | write_cif_reg(base, reg->offset + csi_offset, reg_val); |
|---|
| 726 | + v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, |
|---|
| 727 | + "write and reg[0x%x]:0x%x!!!\n", |
|---|
| 728 | + reg->offset + csi_offset, val); |
|---|
| 720 | 729 | } else { |
|---|
| 721 | 730 | v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, |
|---|
| 722 | 731 | "write reg[%d]:0x%x with OR failed, maybe useless!!!\n", |
|---|
| .. | .. |
|---|
| 1124 | 1133 | cif_dev->reset_watchdog_timer.is_triggered = false; |
|---|
| 1125 | 1134 | cif_dev->reset_watchdog_timer.is_running = false; |
|---|
| 1126 | 1135 | cif_dev->err_state_work.last_timestamp = 0; |
|---|
| 1136 | + cif_dev->is_toisp_reset = false; |
|---|
| 1127 | 1137 | for (i = 0; i < cif_dev->num_channels; i++) |
|---|
| 1128 | 1138 | cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0; |
|---|
| 1129 | 1139 | cif_dev->reset_watchdog_timer.run_cnt = 0; |
|---|
| .. | .. |
|---|
| 1208 | 1218 | cif_dev->is_start_hdr = true; |
|---|
| 1209 | 1219 | cif_dev->reset_watchdog_timer.is_triggered = false; |
|---|
| 1210 | 1220 | cif_dev->reset_watchdog_timer.is_running = false; |
|---|
| 1221 | + cif_dev->is_toisp_reset = false; |
|---|
| 1211 | 1222 | for (i = 0; i < cif_dev->num_channels; i++) |
|---|
| 1212 | 1223 | cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0; |
|---|
| 1213 | 1224 | cif_dev->reset_watchdog_timer.run_cnt = 0; |
|---|
| .. | .. |
|---|
| 1561 | 1572 | |
|---|
| 1562 | 1573 | if (!completion_done(&dev->cmpl_ntf)) |
|---|
| 1563 | 1574 | complete(&dev->cmpl_ntf); |
|---|
| 1564 | | - if (dev->active_sensor && |
|---|
| 1565 | | - (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || |
|---|
| 1566 | | - dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY)) { |
|---|
| 1567 | | - ret = v4l2_subdev_call(dev->active_sensor->sd, |
|---|
| 1568 | | - core, ioctl, |
|---|
| 1569 | | - RKCIF_CMD_SET_CSI_IDX, |
|---|
| 1570 | | - &dev->csi_host_idx); |
|---|
| 1571 | | - if (ret) |
|---|
| 1572 | | - v4l2_err(&dev->v4l2_dev, "set csi idx %d fail\n", dev->csi_host_idx); |
|---|
| 1573 | | - } |
|---|
| 1574 | 1575 | v4l2_info(&dev->v4l2_dev, "Async subdev notifier completed\n"); |
|---|
| 1575 | 1576 | |
|---|
| 1576 | 1577 | return ret; |
|---|
| .. | .. |
|---|
| 1908 | 1909 | INIT_WORK(&dev->reset_work.work, rkcif_reset_work); |
|---|
| 1909 | 1910 | } |
|---|
| 1910 | 1911 | |
|---|
| 1912 | +void rkcif_set_sensor_stream(struct work_struct *work) |
|---|
| 1913 | +{ |
|---|
| 1914 | + struct rkcif_sensor_work *sensor_work = container_of(work, |
|---|
| 1915 | + struct rkcif_sensor_work, |
|---|
| 1916 | + work); |
|---|
| 1917 | + struct rkcif_device *cif_dev = container_of(sensor_work, |
|---|
| 1918 | + struct rkcif_device, |
|---|
| 1919 | + sensor_work); |
|---|
| 1920 | + |
|---|
| 1921 | + v4l2_subdev_call(cif_dev->terminal_sensor.sd, |
|---|
| 1922 | + core, ioctl, |
|---|
| 1923 | + RKMODULE_SET_QUICK_STREAM, |
|---|
| 1924 | + &sensor_work->on); |
|---|
| 1925 | +} |
|---|
| 1926 | + |
|---|
| 1927 | +static void rkcif_deal_err_intr(struct work_struct *work) |
|---|
| 1928 | +{ |
|---|
| 1929 | + struct delayed_work *dwork = to_delayed_work(work); |
|---|
| 1930 | + struct rkcif_device *cif_dev = container_of(dwork, |
|---|
| 1931 | + struct rkcif_device, |
|---|
| 1932 | + work_deal_err); |
|---|
| 1933 | + |
|---|
| 1934 | + cif_dev->intr_mask |= CSI_BANDWIDTH_LACK_V1; |
|---|
| 1935 | + rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_INTEN, CSI_BANDWIDTH_LACK_V1); |
|---|
| 1936 | +} |
|---|
| 1937 | + |
|---|
| 1911 | 1938 | int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int inf_id) |
|---|
| 1912 | 1939 | { |
|---|
| 1913 | 1940 | struct device *dev = cif_dev->dev; |
|---|
| .. | .. |
|---|
| 1927 | 1954 | atomic_set(&cif_dev->pipe.power_cnt, 0); |
|---|
| 1928 | 1955 | atomic_set(&cif_dev->pipe.stream_cnt, 0); |
|---|
| 1929 | 1956 | atomic_set(&cif_dev->power_cnt, 0); |
|---|
| 1957 | + atomic_set(&cif_dev->streamoff_cnt, 0); |
|---|
| 1930 | 1958 | cif_dev->is_start_hdr = false; |
|---|
| 1931 | 1959 | cif_dev->pipe.open = rkcif_pipeline_open; |
|---|
| 1932 | 1960 | cif_dev->pipe.close = rkcif_pipeline_close; |
|---|
| .. | .. |
|---|
| 1940 | 1968 | cif_dev->early_line = 0; |
|---|
| 1941 | 1969 | cif_dev->is_thunderboot = false; |
|---|
| 1942 | 1970 | cif_dev->rdbk_debug = 0; |
|---|
| 1971 | + |
|---|
| 1972 | + cif_dev->resume_mode = 0; |
|---|
| 1973 | + memset(&cif_dev->channels[0].capture_info, 0, sizeof(cif_dev->channels[0].capture_info)); |
|---|
| 1943 | 1974 | if (cif_dev->chip_id == CHIP_RV1126_CIF_LITE) |
|---|
| 1944 | 1975 | cif_dev->isr_hdl = rkcif_irq_lite_handler; |
|---|
| 1945 | 1976 | |
|---|
| 1946 | 1977 | INIT_WORK(&cif_dev->err_state_work.work, rkcif_err_print_work); |
|---|
| 1978 | + INIT_WORK(&cif_dev->sensor_work.work, rkcif_set_sensor_stream); |
|---|
| 1979 | + INIT_DELAYED_WORK(&cif_dev->work_deal_err, rkcif_deal_err_intr); |
|---|
| 1947 | 1980 | |
|---|
| 1948 | 1981 | if (cif_dev->chip_id < CHIP_RV1126_CIF) { |
|---|
| 1949 | 1982 | if (cif_dev->inf_id == RKCIF_MIPI_LVDS) { |
|---|
| .. | .. |
|---|
| 1997 | 2030 | cif_dev->csi_host_idx = of_alias_get_id(node, "rkcif_mipi_lvds"); |
|---|
| 1998 | 2031 | if (cif_dev->csi_host_idx < 0 || cif_dev->csi_host_idx > 5) |
|---|
| 1999 | 2032 | cif_dev->csi_host_idx = 0; |
|---|
| 2033 | + if (cif_dev->hw_dev->is_rk3588s2) { |
|---|
| 2034 | + if (cif_dev->csi_host_idx == 0) |
|---|
| 2035 | + cif_dev->csi_host_idx = 2; |
|---|
| 2036 | + else if (cif_dev->csi_host_idx == 2) |
|---|
| 2037 | + cif_dev->csi_host_idx = 4; |
|---|
| 2038 | + else if (cif_dev->csi_host_idx == 3) |
|---|
| 2039 | + cif_dev->csi_host_idx = 5; |
|---|
| 2040 | + v4l2_info(&cif_dev->v4l2_dev, "rk3588s2 attach to mipi%d\n", |
|---|
| 2041 | + cif_dev->csi_host_idx); |
|---|
| 2042 | + } |
|---|
| 2043 | + cif_dev->csi_host_idx_def = cif_dev->csi_host_idx; |
|---|
| 2000 | 2044 | cif_dev->media_dev.dev = dev; |
|---|
| 2001 | 2045 | v4l2_dev = &cif_dev->v4l2_dev; |
|---|
| 2002 | 2046 | v4l2_dev->mdev = &cif_dev->media_dev; |
|---|
| .. | .. |
|---|
| 2106 | 2150 | struct resource r; |
|---|
| 2107 | 2151 | int ret; |
|---|
| 2108 | 2152 | |
|---|
| 2153 | + cif_dev->is_thunderboot = false; |
|---|
| 2154 | + cif_dev->is_rtt_suspend = false; |
|---|
| 2109 | 2155 | /* Get reserved memory region from Device-tree */ |
|---|
| 2110 | 2156 | np = of_parse_phandle(dev->of_node, "memory-region-thunderboot", 0); |
|---|
| 2111 | 2157 | if (!np) { |
|---|
| .. | .. |
|---|
| 2121 | 2167 | |
|---|
| 2122 | 2168 | cif_dev->resmem_pa = r.start; |
|---|
| 2123 | 2169 | cif_dev->resmem_size = resource_size(&r); |
|---|
| 2124 | | - cif_dev->is_thunderboot = true; |
|---|
| 2170 | + cif_dev->resmem_addr = dma_map_single(dev, phys_to_virt(r.start), |
|---|
| 2171 | + sizeof(struct rkisp_thunderboot_resmem_head), |
|---|
| 2172 | + DMA_BIDIRECTIONAL); |
|---|
| 2173 | + |
|---|
| 2174 | + if (device_property_read_bool(dev, "rtt-suspend")) |
|---|
| 2175 | + cif_dev->is_rtt_suspend = true; |
|---|
| 2176 | + if (IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) |
|---|
| 2177 | + cif_dev->is_thunderboot = true; |
|---|
| 2125 | 2178 | dev_info(dev, "Allocated reserved memory, paddr: 0x%x, size 0x%x\n", |
|---|
| 2126 | 2179 | (u32)cif_dev->resmem_pa, |
|---|
| 2127 | 2180 | (u32)cif_dev->resmem_size); |
|---|
| .. | .. |
|---|
| 2159 | 2212 | if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp)) |
|---|
| 2160 | 2213 | return -ENODEV; |
|---|
| 2161 | 2214 | |
|---|
| 2162 | | - rkcif_attach_hw(cif_dev); |
|---|
| 2215 | + ret = rkcif_attach_hw(cif_dev); |
|---|
| 2216 | + if (ret) |
|---|
| 2217 | + return ret; |
|---|
| 2163 | 2218 | |
|---|
| 2164 | 2219 | rkcif_parse_dts(cif_dev); |
|---|
| 2165 | 2220 | |
|---|
| .. | .. |
|---|
| 2194 | 2249 | sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp); |
|---|
| 2195 | 2250 | del_timer_sync(&cif_dev->reset_watchdog_timer.timer); |
|---|
| 2196 | 2251 | |
|---|
| 2252 | + return 0; |
|---|
| 2253 | +} |
|---|
| 2254 | + |
|---|
| 2255 | +static int __maybe_unused rkcif_sleep_suspend(struct device *dev) |
|---|
| 2256 | +{ |
|---|
| 2257 | + struct rkcif_device *cif_dev = dev_get_drvdata(dev); |
|---|
| 2258 | + |
|---|
| 2259 | + rkcif_stream_suspend(cif_dev, RKCIF_RESUME_CIF); |
|---|
| 2260 | + return 0; |
|---|
| 2261 | +} |
|---|
| 2262 | + |
|---|
| 2263 | +static int __maybe_unused rkcif_sleep_resume(struct device *dev) |
|---|
| 2264 | +{ |
|---|
| 2265 | + struct rkcif_device *cif_dev = dev_get_drvdata(dev); |
|---|
| 2266 | + |
|---|
| 2267 | + rkcif_stream_resume(cif_dev, RKCIF_RESUME_CIF); |
|---|
| 2197 | 2268 | return 0; |
|---|
| 2198 | 2269 | } |
|---|
| 2199 | 2270 | |
|---|
| .. | .. |
|---|
| 2267 | 2338 | #endif |
|---|
| 2268 | 2339 | |
|---|
| 2269 | 2340 | static const struct dev_pm_ops rkcif_plat_pm_ops = { |
|---|
| 2270 | | - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, |
|---|
| 2271 | | - pm_runtime_force_resume) |
|---|
| 2341 | + SET_SYSTEM_SLEEP_PM_OPS(rkcif_sleep_suspend, rkcif_sleep_resume) |
|---|
| 2272 | 2342 | SET_RUNTIME_PM_OPS(rkcif_runtime_suspend, rkcif_runtime_resume, NULL) |
|---|
| 2273 | 2343 | }; |
|---|
| 2274 | 2344 | |
|---|