Merge commit '5eda8fae48807684b2bb82cc88d66106821883dc'

* commit '5eda8fae48807684b2bb82cc88d66106821883dc':
  media: i2c: add mis4001 sensor driver
  media: i2c: add mis2031 sensor driver
  media: i2c: add sc2355 driver
  ARM: configs: rk312x: enable CONFIG_DRM_IGNORE_IOTCL_PERMIT
  media: i2c: sc5336 update register list
  soc: rockchip: minidump: make md_vmalloc_to_page() static
  fiq_debugger: set current_cpu to new cpu after current_cpu is offline
  ARM: dts: rockchip: add rv1106g-evb2-v12-aov-spi-nor.dts
  media: rockchip: vicap: reserve memory according to actual needs when dev change from thunderboot to online
  media: rockchip: vicap fixes error when work on both thunderboot and quick suspend/resume
  video: rockchip: add mpp osal
  soc: rockchip: minidump: don't save peripheral space
  arm64: dts: rockchip: rk3588-linux: support minidump
  media: i2c: max92756: Support V4L2 DV class

Change-Id: Iafef5fffb4cd5d5020780e37882b60638d43de51

Conflicts:
	drivers/media/i2c/Kconfig
	drivers/media/i2c/Makefile
This commit is contained in:
Tao Huang
2023-11-22 17:54:23 +08:00
29 changed files with 5523 additions and 131 deletions

View File

@@ -1151,6 +1151,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
rv1106g-evb2-v10-dual-camera.dtb \
rv1106g-evb2-v11-emmc.dtb \
rv1106g-evb2-v11-trailcam-emmc.dtb \
rv1106g-evb2-v12-aov-spi-nor.dtb \
rv1106g-evb2-v12-nofastae-emmc.dtb \
rv1106g-evb2-v12-nofastae-spi-nand.dtb \
rv1106g-evb2-v12-nofastae-spi-nor.dtb \

View File

@@ -0,0 +1,29 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
*/
/dts-v1/;
#include "rv1106g-evb2-v10.dts"
/ {
model = "Rockchip RV1106G EVB2 V12 Board";
compatible = "rockchip,rv1106g-evb2-v12", "rockchip,rv1106";
};
&rkcif_mipi_lvds {
rtt-suspend;
status = "okay";
};
&rkisp_vir0 {
memory-region-thunderboot = <&rkisp_thunderboot>;
rtt-suspend;
status = "okay";
};
&thunder_boot_service {
memory-no-free;
status = "okay";
};

View File

@@ -47,7 +47,6 @@ CONFIG_DEBUG_GPIO=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DNS_RESOLVER is not set
# CONFIG_DRM_IGNORE_IOTCL_PERMIT is not set
# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
# CONFIG_ECRYPT_FS is not set
# CONFIG_ETHERNET is not set
@@ -227,7 +226,9 @@ CONFIG_GS_MMA7660=y
# CONFIG_GS_SC7A30 is not set
# CONFIG_GYROSCOPE_DEVICE is not set
# CONFIG_HALL_DEVICE is not set
# CONFIG_IAM20680_ACC is not set
# CONFIG_ICM2060X_ACC is not set
# CONFIG_ICM4260X_ACC is not set
CONFIG_INLINE_READ_UNLOCK=y
CONFIG_INLINE_READ_UNLOCK_IRQ=y
CONFIG_INLINE_SPIN_UNLOCK_IRQ=y

View File

@@ -46,7 +46,6 @@ CONFIG_DEBUG_GPIO=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DNS_RESOLVER is not set
# CONFIG_DRM_IGNORE_IOTCL_PERMIT is not set
# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
# CONFIG_ECRYPT_FS is not set
# CONFIG_ETHERNET is not set
@@ -232,7 +231,9 @@ CONFIG_GS_MMA7660=y
# CONFIG_GS_SC7A30 is not set
# CONFIG_GYROSCOPE_DEVICE is not set
# CONFIG_HALL_DEVICE is not set
# CONFIG_IAM20680_ACC is not set
# CONFIG_ICM2060X_ACC is not set
# CONFIG_ICM4260X_ACC is not set
# CONFIG_INFTL is not set
CONFIG_INLINE_READ_UNLOCK=y
CONFIG_INLINE_READ_UNLOCK_IRQ=y

View File

@@ -24,7 +24,6 @@ CONFIG_DEBUG_GPIO=y
# CONFIG_DEBUG_LIST is not set
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_DNS_RESOLVER is not set
# CONFIG_DRM_IGNORE_IOTCL_PERMIT is not set
# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
CONFIG_DRM_UDL=y
# CONFIG_ECRYPT_FS is not set
@@ -56,8 +55,6 @@ CONFIG_RUNTIME_TESTING_MENU=y
# CONFIG_SCHED_STACK_END_CHECK is not set
CONFIG_SENSOR_DEVICE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_SND_SOC_ROCKCHIP_HDMI=y
CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y
CONFIG_SOFTLOCKUP_DETECTOR=y
# CONFIG_SPI_SPIDEV is not set
# CONFIG_TEE is not set
@@ -110,7 +107,9 @@ CONFIG_GS_MMA7660=y
# CONFIG_GS_SC7A30 is not set
# CONFIG_GYROSCOPE_DEVICE is not set
# CONFIG_HALL_DEVICE is not set
# CONFIG_IAM20680_ACC is not set
# CONFIG_ICM2060X_ACC is not set
# CONFIG_ICM4260X_ACC is not set
# CONFIG_INTERVAL_TREE_TEST is not set
CONFIG_IPC_NS=y
# CONFIG_LIGHT_DEVICE is not set

View File

@@ -24,7 +24,6 @@ CONFIG_DEBUG_GPIO=y
# CONFIG_DEBUG_LIST is not set
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_DNS_RESOLVER is not set
# CONFIG_DRM_IGNORE_IOTCL_PERMIT is not set
# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
CONFIG_DRM_UDL=y
# CONFIG_ECRYPT_FS is not set
@@ -58,7 +57,6 @@ CONFIG_RUNTIME_TESTING_MENU=y
# CONFIG_SCHED_STACK_END_CHECK is not set
CONFIG_SENSOR_DEVICE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y
CONFIG_SOFTLOCKUP_DETECTOR=y
# CONFIG_SPI_SPIDEV is not set
# CONFIG_TEE is not set
@@ -111,7 +109,9 @@ CONFIG_GS_MMA7660=y
# CONFIG_GS_SC7A30 is not set
# CONFIG_GYROSCOPE_DEVICE is not set
# CONFIG_HALL_DEVICE is not set
# CONFIG_IAM20680_ACC is not set
# CONFIG_ICM2060X_ACC is not set
# CONFIG_ICM4260X_ACC is not set
# CONFIG_INTERVAL_TREE_TEST is not set
CONFIG_IPC_NS=y
# CONFIG_LIGHT_DEVICE is not set
@@ -128,6 +128,7 @@ CONFIG_PID_NS=y
# CONFIG_RBTREE_TEST is not set
# CONFIG_REED_SOLOMON_TEST is not set
# CONFIG_ROCKCHIP_MMC_VENDOR_STORAGE is not set
# CONFIG_ROCKCHIP_RAM_VENDOR_STORAGE is not set
# CONFIG_ROCKCHIP_RGA2 is not set
# CONFIG_STK8BAXX_ACC is not set
# CONFIG_TEMPERATURE_DEVICE is not set

View File

@@ -60,6 +60,13 @@
};
};
minidump: minidump {
compatible = "rockchip,minidump";
smem-region = <&minidump_smem>;
minidump-region = <&minidump_mem>;
status = "disabled";
};
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
@@ -84,12 +91,28 @@
ramoops: ramoops@110000 {
compatible = "ramoops";
reg = <0x0 0x110000 0x0 0xf0000>;
record-size = <0x20000>;
/* 0x110000 to 0x1f0000 is for ramoops */
reg = <0x0 0x110000 0x0 0xe0000>;
boot-log-size = <0x8000>; /* do not change */
boot-log-count = <0x1>; /* do not change */
console-size = <0x80000>;
pmsg-size = <0x30000>;
ftrace-size = <0x00000>;
pmsg-size = <0x50000>;
record-size = <0x14000>;
};
minidump_smem: minidump-smem@1f0000 {
reg = <0x0 0x1f0000 0x0 0x100>; /* do not change */
no-map;
status = "disabled";
};
minidump_mem: minidump-mem@c000000 {
reg = <0x0 0x0c000000 0x0 0x2000000>; /* changing according to your project */
no-map;
status = "disabled";
};
};
};

View File

@@ -791,6 +791,26 @@ config VIDEO_JX_K17
config VIDEO_MAX9271_LIB
tristate
config VIDEO_MIS2031
tristate "ImageDesign mis2031 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the ImageDesign
MIS2031 camera.
config VIDEO_MIS4001
tristate "ImageDesign mis4001 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the ImageDesign
MIS4001 camera.
config VIDEO_MT9M001
tristate "mt9m001 support"
depends on I2C && VIDEO_DEV
@@ -1712,6 +1732,17 @@ config VIDEO_SC2336
This is a Video4Linux2 sensor driver for the SmartSens
SC2336 camera.
config VIDEO_SC2355
tristate "SmartSens SC2355 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
Support for the SmartSens SC2355 sensor.
To compile this driver as a module, choose M here: the
module will be called sc2355.
config VIDEO_SC301IOT
tristate "SmartSens SC301IOT sensor support"
depends on I2C && VIDEO_DEV

View File

@@ -121,6 +121,8 @@ obj-$(CONFIG_VIDEO_MAX96712) += max96712.o
obj-$(CONFIG_VIDEO_MAX96714) += max96714.o
obj-$(CONFIG_VIDEO_MAX96722) += max96722.o
obj-$(CONFIG_VIDEO_MAX96756) += max96756.o
obj-$(CONFIG_VIDEO_MIS2031) += mis2031.o
obj-$(CONFIG_VIDEO_MIS4001) += mis4001.o
obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
@@ -220,6 +222,7 @@ obj-$(CONFIG_VIDEO_SC223A) += sc223a.o
obj-$(CONFIG_VIDEO_SC230AI) += sc230ai.o
obj-$(CONFIG_VIDEO_SC2310) += sc2310.o
obj-$(CONFIG_VIDEO_SC2336) += sc2336.o
obj-$(CONFIG_VIDEO_SC2355) += sc2355.o
obj-$(CONFIG_VIDEO_SC301IOT) += sc301iot.o
obj-$(CONFIG_VIDEO_SC3336) += sc3336.o
obj-$(CONFIG_VIDEO_SC3338) += sc3338.o

View File

@@ -6,6 +6,8 @@
*
* V0.0X01.0X00 first version.
*
* V0.0X01.0X01
* - Support V4L2 DV class features
*/
#define DEBUG
@@ -22,21 +24,29 @@
#include <linux/version.h>
#include <linux/compat.h>
#include <linux/rk-camera-module.h>
#include <linux/v4l2-dv-timings.h>
#include <media/media-entity.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-dv-timings.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#include <linux/pinctrl/consumer.h>
#include "max96756.h"
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00)
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01)
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-3)");
#ifndef V4L2_CID_DIGITAL_GAIN
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
#endif
#define MAX96756_LINK_FREQ_450MHZ (450 * 1000 * 1000UL)
#define MAX96756_PIXEL_RATE (MAX96756_LINK_FREQ_450MHZ * 2LL * 4LL / 8LL)
#define MAX96756_LINK_FREQ_MHZ(x) ((x)*1000 * 1000ULL)
#define MAX96756_PIXEL_RATE (450LL * 2 * 4 / 8)
#define MAX96756_REG_CHIP_ID 0x0D
#define CHIP_ID 0x90
@@ -92,30 +102,43 @@ struct max96756_mode {
const struct regval *reg_list;
};
static const struct v4l2_dv_timings_cap max96756_timings_cap = {
.type = V4L2_DV_BT_656_1120,
.reserved = { 0 },
V4L2_INIT_BT_TIMINGS(
1, 10000, 1, 10000, 0, 800000000,
V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED |
V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM)
};
struct max96756 {
struct i2c_client *client;
struct clk *xvclk;
struct gpio_desc *pwdn_gpio;
struct regulator_bulk_data supplies[MAX96756_NUM_SUPPLIES];
struct pinctrl *pinctrl;
struct pinctrl_state *pins_default;
struct pinctrl_state *pins_sleep;
struct gpio_desc *lock_gpio;
int lock_irq;
struct delayed_work delayed_work_lock;
struct work_struct work_i2c_poll;
struct v4l2_subdev subdev;
struct media_pad pad;
struct v4l2_fwnode_endpoint bus_cfg;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl *exposure;
struct v4l2_ctrl *anal_gain;
struct v4l2_ctrl *digi_gain;
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank;
struct v4l2_ctrl *lock_det;
struct v4l2_ctrl *pixel_rate;
struct v4l2_ctrl *link_freq;
struct v4l2_ctrl *test_pattern;
struct v4l2_dv_timings timings;
struct mutex mutex;
bool streaming;
@@ -223,8 +246,22 @@ static const struct max96756_mode supported_modes[] = {
},
};
static const struct max96756_mode supported_modes_dcphy[] = {
{
.width = 1920,
.height = 1080,
.max_fps = {
.numerator = 10000,
.denominator = 600000,
},
.reg_list = max96756_mipi_1080p_60fps,
.link_freq_idx = 1,
},
};
static const s64 link_freq_items[] = {
MAX96756_LINK_FREQ_450MHZ,
MAX96756_LINK_FREQ_MHZ(450),
MAX96756_LINK_FREQ_MHZ(900),
};
static int max96756_write_reg(struct i2c_client *client, u16 reg, u32 len,
@@ -478,6 +515,9 @@ static long max96756_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
case RKMODULE_GET_MODULE_INFO:
max96756_get_module_inf(max96756, (struct rkmodule_inf *)arg);
break;
case RKMODULE_GET_HDMI_MODE:
*(int *)arg = RKMODULE_HDMIIN_MODE;
break;
case RKMODULE_SET_QUICK_STREAM:
stream = *((u32 *)arg);
if (stream)
@@ -522,11 +562,11 @@ static long max96756_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
{
void __user *up = compat_ptr(arg);
struct rkmodule_inf *inf;
struct rkmodule_awb_cfg *cfg;
struct rkmodule_vicap_reset_info *vicap_rst_inf;
long ret = 0;
int *seq;
u32 stream = 0;
struct rkmodule_csi_dphy_param *dphy_param;
switch (cmd) {
case RKMODULE_GET_MODULE_INFO:
@@ -544,19 +584,20 @@ static long max96756_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
}
kfree(inf);
break;
case RKMODULE_AWB_CFG:
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
if (!cfg) {
case RKMODULE_GET_HDMI_MODE:
seq = kzalloc(sizeof(*seq), GFP_KERNEL);
if (!seq) {
ret = -ENOMEM;
return ret;
}
ret = copy_from_user(cfg, up, sizeof(*cfg));
if (!ret)
ret = max96756_ioctl(sd, cmd, cfg);
else
ret = -EFAULT;
kfree(cfg);
ret = max96756_ioctl(sd, cmd, seq);
if (!ret) {
ret = copy_to_user(up, seq, sizeof(*seq));
if (ret)
ret = -EFAULT;
}
kfree(seq);
break;
case RKMODULE_GET_VICAP_RST_INFO:
vicap_rst_inf = kzalloc(sizeof(*vicap_rst_inf), GFP_KERNEL);
@@ -588,21 +629,6 @@ static long max96756_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
ret = -EFAULT;
kfree(vicap_rst_inf);
break;
case RKMODULE_GET_START_STREAM_SEQ:
seq = kzalloc(sizeof(*seq), GFP_KERNEL);
if (!seq) {
ret = -ENOMEM;
return ret;
}
ret = max96756_ioctl(sd, cmd, seq);
if (!ret) {
ret = copy_to_user(up, seq, sizeof(*seq));
if (ret)
ret = -EFAULT;
}
kfree(seq);
break;
case RKMODULE_SET_QUICK_STREAM:
ret = copy_from_user(&stream, up, sizeof(u32));
if (!ret)
@@ -610,6 +636,35 @@ static long max96756_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
else
ret = -EFAULT;
break;
case RKMODULE_SET_CSI_DPHY_PARAM:
dphy_param = kzalloc(sizeof(*dphy_param), GFP_KERNEL);
if (!dphy_param) {
ret = -ENOMEM;
return ret;
}
ret = copy_from_user(dphy_param, up, sizeof(*dphy_param));
if (!ret)
ret = max96756_ioctl(sd, cmd, dphy_param);
else
ret = -EFAULT;
kfree(dphy_param);
break;
case RKMODULE_GET_CSI_DPHY_PARAM:
dphy_param = kzalloc(sizeof(*dphy_param), GFP_KERNEL);
if (!dphy_param) {
ret = -ENOMEM;
return ret;
}
ret = max96756_ioctl(sd, cmd, dphy_param);
if (!ret) {
ret = copy_to_user(up, dphy_param, sizeof(*dphy_param));
if (ret)
ret = -EFAULT;
}
kfree(dphy_param);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -619,6 +674,19 @@ static long max96756_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
}
#endif
static int max96756_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
switch (sub->type) {
case V4L2_EVENT_SOURCE_CHANGE:
return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
case V4L2_EVENT_CTRL:
return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
default:
return -EINVAL;
}
}
static int __max96756_start_stream(struct max96756 *max96756)
{
int ret;
@@ -656,6 +724,143 @@ static int __max96756_stop_stream(struct max96756 *max96756)
return ret;
}
static bool max96756_match_timings(const struct v4l2_dv_timings *t1,
const struct v4l2_dv_timings *t2)
{
if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120)
return false;
if (t1->bt.width == t2->bt.width && t1->bt.height == t2->bt.height &&
t1->bt.interlaced == t2->bt.interlaced)
return true;
return false;
}
static inline bool max96756_detect_lock_status(struct max96756 *max96756)
{
bool ret;
int val, i, cnt;
/* if not use lock gpio */
if (!max96756->lock_gpio)
return true;
cnt = 0;
for (i = 0; i < 5; i++) {
val = gpiod_get_value(max96756->lock_gpio);
if (val > 0)
cnt++;
usleep_range(500, 600);
}
ret = (cnt >= 3) ? true : false;
v4l2_dbg(1, debug, &max96756->subdev, "%s: %d\n", __func__, ret);
return ret;
}
static bool max96756_check_signal(struct max96756 *max96756)
{
u32 val = 0;
max96756_read_reg(max96756->client, 0x11A, MAX96756_REG_VALUE_08BIT,
&val);
return val & (1 << 6);
}
static int max96756_g_input_status(struct v4l2_subdev *sd, u32 *status)
{
struct max96756 *max96756 = to_max96756(sd);
*status = 0;
*status |= max96756_check_signal(max96756) ? V4L2_IN_ST_NO_SIGNAL : 0;
v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status);
return 0;
}
static int max96756_s_dv_timings(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings)
{
struct max96756 *max96756 = to_max96756(sd);
if (!timings)
return -EINVAL;
if (debug)
v4l2_print_dv_timings(sd->name, "s_dv_timings: ", timings,
false);
if (max96756_match_timings(&max96756->timings, timings)) {
v4l2_dbg(1, debug, sd, "%s: no change\n", __func__);
return 0;
}
if (!v4l2_valid_dv_timings(timings, &max96756_timings_cap, NULL,
NULL)) {
v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__);
return -ERANGE;
}
max96756->timings = *timings;
__max96756_stop_stream(max96756);
return 0;
}
static int max96756_g_dv_timings(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings)
{
struct max96756 *max96756 = to_max96756(sd);
*timings = max96756->timings;
return 0;
}
static int max96756_enum_dv_timings(struct v4l2_subdev *sd,
struct v4l2_enum_dv_timings *timings)
{
if (timings->pad != 0)
return -EINVAL;
return v4l2_enum_dv_timings_cap(timings, &max96756_timings_cap, NULL,
NULL);
}
static int max96756_query_dv_timings(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings)
{
struct max96756 *max96756 = to_max96756(sd);
*timings = max96756->timings;
if (debug)
v4l2_print_dv_timings(sd->name, "query_dv_timings: ", timings,
false);
if (!v4l2_valid_dv_timings(timings, &max96756_timings_cap, NULL,
NULL)) {
v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__);
return -ERANGE;
}
return 0;
}
static int max96756_dv_timings_cap(struct v4l2_subdev *sd,
struct v4l2_dv_timings_cap *cap)
{
if (cap->pad != 0)
return -EINVAL;
*cap = max96756_timings_cap;
return 0;
}
static int max96756_s_stream(struct v4l2_subdev *sd, int on)
{
struct max96756 *max96756 = to_max96756(sd);
@@ -831,8 +1036,6 @@ static int max96756_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
{
config->type = V4L2_MBUS_CSI2_DPHY;
config->flags = V4L2_MBUS_CSI2_4_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CHANNEL_1 | V4L2_MBUS_CSI2_CHANNEL_2 |
V4L2_MBUS_CSI2_CHANNEL_3 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
return 0;
@@ -866,6 +1069,8 @@ static const struct v4l2_subdev_internal_ops max96756_internal_ops = {
static const struct v4l2_subdev_core_ops max96756_core_ops = {
.s_power = max96756_s_power,
.subscribe_event = max96756_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
.ioctl = max96756_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl32 = max96756_compat_ioctl32,
@@ -873,6 +1078,10 @@ static const struct v4l2_subdev_core_ops max96756_core_ops = {
};
static const struct v4l2_subdev_video_ops max96756_video_ops = {
.g_input_status = max96756_g_input_status,
.s_dv_timings = max96756_s_dv_timings,
.g_dv_timings = max96756_g_dv_timings,
.query_dv_timings = max96756_query_dv_timings,
.s_stream = max96756_s_stream,
.g_frame_interval = max96756_g_frame_interval,
};
@@ -885,6 +1094,8 @@ static const struct v4l2_subdev_pad_ops max96756_pad_ops = {
.set_fmt = max96756_set_fmt,
.get_selection = max96756_get_selection,
.get_mbus_config = max96756_g_mbus_config,
.enum_dv_timings = max96756_enum_dv_timings,
.dv_timings_cap = max96756_dv_timings_cap,
};
static const struct v4l2_subdev_ops max96756_subdev_ops = {
@@ -901,20 +1112,26 @@ static int max96756_initialize_controls(struct max96756 *max96756)
handler = &max96756->ctrl_handler;
mode = max96756->cur_mode;
ret = v4l2_ctrl_handler_init(handler, 2);
ret = v4l2_ctrl_handler_init(handler, 3);
if (ret)
return ret;
handler->lock = &max96756->mutex;
max96756->link_freq = v4l2_ctrl_new_int_menu(
handler, NULL, V4L2_CID_LINK_FREQ, 1, 0, link_freq_items);
max96756->link_freq =
v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,
ARRAY_SIZE(link_freq_items) - 1, 0,
link_freq_items);
max96756->pixel_rate =
v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 0,
MAX96756_PIXEL_RATE, 1, MAX96756_PIXEL_RATE);
max96756->lock_det = v4l2_ctrl_new_std(
handler, NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0);
__v4l2_ctrl_s_ctrl_int64(max96756->pixel_rate, MAX96756_PIXEL_RATE);
__v4l2_ctrl_s_ctrl(max96756->link_freq, mode->link_freq_idx);
__v4l2_ctrl_s_ctrl(max96756->lock_det,
max96756_detect_lock_status(max96756));
if (handler->error) {
ret = handler->error;
@@ -952,6 +1169,29 @@ static int max96756_check_sensor_id(struct max96756 *max96756,
return 0;
}
static void max96756_delayed_work_lock(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
struct max96756 *max96756 =
container_of(dwork, struct max96756, delayed_work_lock);
__v4l2_ctrl_s_ctrl(max96756->lock_det,
max96756_detect_lock_status(max96756));
}
static irqreturn_t lock_irq_handler(int irq, void *dev_id)
{
struct max96756 *max96756 = dev_id;
mutex_lock(&max96756->mutex);
if (max96756->streaming)
schedule_delayed_work(&max96756->delayed_work_lock,
msecs_to_jiffies(50));
mutex_unlock(&max96756->mutex);
return IRQ_HANDLED;
}
static int max96756_configure_regulators(struct max96756 *max96756)
{
unsigned int i;
@@ -964,8 +1204,7 @@ static int max96756_configure_regulators(struct max96756 *max96756)
max96756->supplies);
}
static int max96756_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int max96756_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct device_node *node = dev->of_node;
@@ -1001,6 +1240,25 @@ static int max96756_probe(struct i2c_client *client,
if (IS_ERR(max96756->pwdn_gpio))
dev_warn(dev, "Failed to get pwdn-gpios\n");
max96756->lock_gpio = devm_gpiod_get_optional(dev, "lock", GPIOD_IN);
if (IS_ERR(max96756->lock_gpio)) {
dev_warn(dev, "failed to get lock gpio, will use i2c poll\n");
} else {
max96756->lock_irq = gpiod_to_irq(max96756->lock_gpio);
if (max96756->lock_irq < 0)
dev_err(dev, "failed to get lock irq, maybe no use\n");
ret = devm_request_threaded_irq(
dev, max96756->lock_irq, NULL, lock_irq_handler,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
IRQF_ONESHOT,
"max96756", max96756);
if (ret)
dev_err(dev,
"failed to register lock irq (%d), maybe no use\n",
ret);
}
ret = max96756_configure_regulators(max96756);
if (ret) {
dev_err(dev, "Failed to get power regulators\n");
@@ -1036,9 +1294,12 @@ static int max96756_probe(struct i2c_client *client,
if (ret)
goto err_power_off;
INIT_DELAYED_WORK(&max96756->delayed_work_lock,
max96756_delayed_work_lock);
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
sd->internal_ops = &max96756_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
#endif
#if defined(CONFIG_MEDIA_CONTROLLER)
max96756->pad.flags = MEDIA_PAD_FL_SOURCE;
@@ -1088,6 +1349,8 @@ static int max96756_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct max96756 *max96756 = to_max96756(sd);
cancel_delayed_work_sync(&max96756->delayed_work_lock);
v4l2_async_unregister_subdev(sd);
#if defined(CONFIG_MEDIA_CONTROLLER)
media_entity_cleanup(&sd->entity);
@@ -1122,26 +1385,13 @@ static struct i2c_driver max96756_i2c_driver = {
.pm = &max96756_pm_ops,
.of_match_table = of_match_ptr(max96756_of_match),
},
.probe = &max96756_probe,
.probe_new = &max96756_probe,
.remove = &max96756_remove,
.id_table = max96756_match_id,
};
int max96756_sensor_mod_init(void)
{
return i2c_add_driver(&max96756_i2c_driver);
}
module_i2c_driver(max96756_i2c_driver);
#ifndef CONFIG_VIDEO_REVERSE_IMAGE
device_initcall_sync(max96756_sensor_mod_init);
#endif
static void __exit sensor_mod_exit(void)
{
i2c_del_driver(&max96756_i2c_driver);
}
module_exit(sensor_mod_exit);
MODULE_DESCRIPTION("Maxim max96756 sensor driver");
MODULE_DESCRIPTION("Maxim MAX96756 GMSL1/2 CSI display deserializer driver");
MODULE_AUTHOR("Cody Xie <cody.xie@rock-chips.com>");
MODULE_LICENSE("GPL");

1651
drivers/media/i2c/mis2031.c Normal file

File diff suppressed because it is too large Load Diff

1637
drivers/media/i2c/mis4001.c Normal file

File diff suppressed because it is too large Load Diff

1522
drivers/media/i2c/sc2355.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -51,7 +51,7 @@
#define SC5336_REG_EXPOSURE_H 0x3e00
#define SC5336_REG_EXPOSURE_M 0x3e01
#define SC5336_REG_EXPOSURE_L 0x3e02
#define SC5336_EXPOSURE_MIN 1
#define SC5336_EXPOSURE_MIN 2
#define SC5336_EXPOSURE_STEP 1
#define SC5336_VTS_MAX 0x7fff
@@ -244,7 +244,7 @@ static const struct regval sc5336_linear_10_2880x1620_regs[] = {
{0x3633, 0x33},
{0x3638, 0xcf},
{0x363f, 0xc0},
{0x3641, 0x20},
{0x3641, 0x38},
{0x3670, 0x56},
{0x3674, 0xc0},
{0x3675, 0xa0},
@@ -287,6 +287,7 @@ static const struct regval sc5336_linear_10_2880x1620_regs[] = {
{0x37fb, 0x24},
{0x37fc, 0x01},
{0x37fd, 0x36},
{0x3900, 0x0d},
{0x3901, 0x00},
{0x3904, 0x04},
{0x3905, 0x8c},
@@ -866,6 +867,7 @@ static long sc5336_compat_ioctl32(struct v4l2_subdev *sd,
static int __sc5336_start_stream(struct sc5336 *sc5336)
{
int ret;
u32 chip_version = 0;
if (!sc5336->is_thunderboot) {
ret = sc5336_write_array(sc5336->client, sc5336->cur_mode->reg_list);
@@ -877,6 +879,22 @@ static int __sc5336_start_stream(struct sc5336 *sc5336)
if (ret)
return ret;
}
ret = sc5336_read_reg(sc5336->client, 0x3040, SC5336_REG_VALUE_08BIT, &chip_version);
if (chip_version == 0x00) {
ret |= sc5336_write_reg(sc5336->client, 0x3258, SC5336_REG_VALUE_08BIT, 0x0c);
ret |= sc5336_write_reg(sc5336->client, 0x3249, SC5336_REG_VALUE_08BIT, 0x0b);
ret |= sc5336_write_reg(sc5336->client, 0x3934, SC5336_REG_VALUE_08BIT, 0x0a);
ret |= sc5336_write_reg(sc5336->client, 0x3935, SC5336_REG_VALUE_08BIT, 0x00);
ret |= sc5336_write_reg(sc5336->client, 0x3937, SC5336_REG_VALUE_08BIT, 0x75);
} else if (chip_version == 0x03) {
ret |= sc5336_write_reg(sc5336->client, 0x3258, SC5336_REG_VALUE_08BIT, 0x08);
ret |= sc5336_write_reg(sc5336->client, 0x3249, SC5336_REG_VALUE_08BIT, 0x07);
ret |= sc5336_write_reg(sc5336->client, 0x3934, SC5336_REG_VALUE_08BIT, 0x05);
ret |= sc5336_write_reg(sc5336->client, 0x3935, SC5336_REG_VALUE_08BIT, 0x07);
ret |= sc5336_write_reg(sc5336->client, 0x3937, SC5336_REG_VALUE_08BIT, 0x74);
}
if (ret)
return ret;
return sc5336_write_reg(sc5336->client, SC5336_REG_CTRL_MODE,
SC5336_REG_VALUE_08BIT, SC5336_MODE_STREAMING);

View File

@@ -4506,12 +4506,55 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num)
struct rkcif_rx_buffer *buf;
struct rkcif_device *dev = stream->cifdev;
struct sditf_priv *priv = dev->sditf[0];
struct v4l2_subdev *sd;
int i = 0;
unsigned long flags;
phys_addr_t resmem_free_start;
phys_addr_t resmem_free_end;
u32 share_head_size = 0;
if (!priv)
return;
sd = get_rkisp_sd(dev->sditf[0]);
if (!sd)
return;
if (dev->is_rtt_suspend && dev->is_thunderboot) {
stream->curr_buf_toisp = NULL;
stream->next_buf_toisp = NULL;
INIT_LIST_HEAD(&stream->rx_buf_head);
for (i = 0; i < buf_num; i++) {
buf = &stream->rx_buf[i];
if (buf->dbufs.is_init)
v4l2_subdev_call(sd, core, ioctl,
RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs);
buf->dummy.is_free = true;
}
if (IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) {
share_head_size = dev->thunderboot_sensor_num * sizeof(struct rkisp32_thunderboot_resmem_head);
if (share_head_size != dev->share_mem_size)
v4l2_info(&stream->cifdev->v4l2_dev,
"share mem head error, rtt head size %d, arm head size %d\n",
dev->share_mem_size, share_head_size);
resmem_free_start = dev->resmem_pa + share_head_size + dev->nr_buf_size;
resmem_free_end = dev->resmem_pa + dev->resmem_size;
v4l2_info(&stream->cifdev->v4l2_dev,
"free reserved mem start 0x%x, end 0x%x, share_head_size 0x%x, nr_buf_size 0x%x\n",
(u32)resmem_free_start, (u32)resmem_free_end, share_head_size, dev->nr_buf_size);
free_reserved_area(phys_to_virt(resmem_free_start),
phys_to_virt(resmem_free_end),
-1, "rkisp_thunderboot");
}
atomic_set(&stream->buf_cnt, 0);
stream->total_buf_num = 0;
stream->rx_buf_num = 0;
return;
}
spin_lock_irqsave(&stream->vbq_lock, flags);
stream->curr_buf_toisp = NULL;
stream->next_buf_toisp = NULL;
@@ -4524,6 +4567,9 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num)
buf = &stream->rx_buf[i];
if (buf->dummy.is_free)
continue;
if (buf->dbufs.is_init)
v4l2_subdev_call(sd, core, ioctl,
RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs);
if (!dev->is_thunderboot)
rkcif_free_buffer(dev, &buf->dummy);
else
@@ -4531,6 +4577,7 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num)
atomic_dec(&stream->buf_cnt);
stream->total_buf_num--;
}
stream->rx_buf_num = 0;
if (dev->is_thunderboot) {
spin_unlock_irqrestore(&dev->buffree_lock, flags);
@@ -4541,6 +4588,7 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num)
"free rx_buf, buf_num %d\n", buf_num);
}
static void rkcif_get_resmem_head(struct rkcif_device *cif_dev);
int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num)
{
struct rkcif_device *dev = stream->cifdev;
@@ -4588,10 +4636,12 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num)
dummy->is_need_vaddr = true;
dummy->is_need_dbuf = true;
if (dev->is_thunderboot) {
if (i == 0)
rkcif_get_resmem_head(dev);
buf->buf_idx = i;
ret = rkcif_alloc_reserved_mem_buf(dev, buf);
if (ret) {
priv->buf_num = i;
stream->rx_buf_num = i;
v4l2_info(&dev->v4l2_dev,
"reserved mem support alloc buf num %d, require buf num %d\n",
i, buf_num);
@@ -4604,7 +4654,7 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num)
} else {
ret = rkcif_alloc_buffer(dev, dummy);
if (ret) {
priv->buf_num = i;
stream->rx_buf_num = i;
v4l2_info(&dev->v4l2_dev,
"alloc buf num %d, require buf num %d\n",
i, buf_num);
@@ -4627,10 +4677,10 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num)
}
i++;
if (!dev->is_thunderboot && i >= buf_num) {
priv->buf_num = buf_num;
stream->rx_buf_num = buf_num;
break;
} else if (i >= RKISP_VICAP_BUF_CNT_MAX) {
priv->buf_num = i;
stream->rx_buf_num = i;
v4l2_info(&dev->v4l2_dev,
"reserved mem alloc buf num %d\n", i);
break;
@@ -4639,9 +4689,9 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num)
"init rx_buf,dma_addr 0x%llx size: 0x%x\n",
(u64)dummy->dma_addr, pixm->plane_fmt[0].sizeimage);
}
if (priv->buf_num) {
stream->total_buf_num = priv->buf_num;
atomic_set(&stream->buf_cnt, priv->buf_num);
if (stream->rx_buf_num) {
stream->total_buf_num = stream->rx_buf_num;
atomic_set(&stream->buf_cnt, stream->rx_buf_num);
return 0;
} else {
return -EINVAL;
@@ -6559,6 +6609,7 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id)
stream->is_stop_capture = false;
stream->is_single_cap = false;
atomic_set(&stream->buf_cnt, 0);
stream->rx_buf_num = 0;
}
static int rkcif_fh_open(struct file *filp)
@@ -10303,10 +10354,14 @@ static void rkcif_get_resmem_head(struct rkcif_device *cif_dev)
head = &tmp->head;
cif_dev->resume_mode = head->rtt_mode;
cif_dev->nr_buf_size = head->nr_buf_size;
cif_dev->share_mem_size = head->share_mem_size;
cif_dev->thunderboot_sensor_num = head->camera_num;
}
}
v4l2_err(&cif_dev->v4l2_dev,
"get camera index %02x, resume_mode 0x%x\n", cam_idx, cif_dev->resume_mode);
"get camera index %02x, resume_mode 0x%x, nr_buf_size %d\n",
cam_idx, cif_dev->resume_mode, cif_dev->nr_buf_size);
}
static int rkcif_subdevs_set_power(struct rkcif_device *cif_dev, int on)
@@ -10551,20 +10606,31 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode)
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
if (priv) {
if (capture_mode == RKCIF_STREAM_MODE_TOISP)
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) {
sditf_change_to_online(priv);
else
if (cif_dev->resume_mode == RKISP_RTT_MODE_MULTI_FRAME &&
stream->rx_buf_num &&
(priv->hdr_cfg.hdr_mode == NO_HDR ||
(priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 1) ||
(priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id == 2)))
rkcif_free_rx_buf(stream, priv->buf_num);
else if (!stream->rx_buf_num &&
((priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 0) ||
(priv->hdr_cfg.hdr_mode == HDR_X3 && (stream->id == 0 || stream->id == 1))))
rkcif_init_rx_buf(stream, 1);
} else {
sditf_disable_immediately(priv);
if (!stream->rx_buf_num &&
capture_mode == RKCIF_STREAM_MODE_TOISP_RDBK) {
if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME)
rkcif_init_rx_buf(stream, 1);
else
rkcif_init_rx_buf(stream, priv->buf_num);
}
}
}
if (!stream->total_buf_num && priv &&
(capture_mode == RKCIF_STREAM_MODE_TOISP_RDBK ||
(capture_mode == RKCIF_STREAM_MODE_TOISP &&
((priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 0) ||
(priv->hdr_cfg.hdr_mode == HDR_X3 && (stream->id == 0 || stream->id == 1))))))
rkcif_init_rx_buf(stream, 1);
if (priv && cif_dev->resume_mode == RKISP_RTT_MODE_MULTI_FRAME && stream->total_buf_num)
rkcif_init_rx_buf(stream, priv->buf_num);
stream->lack_buf_cnt = 0;
if (cif_dev->active_sensor &&

View File

@@ -530,6 +530,7 @@ struct rkcif_stream {
struct rkcif_rx_buffer rx_buf[RKISP_VICAP_BUF_CNT_MAX];
struct list_head rx_buf_head;
int total_buf_num;
int rx_buf_num;
u64 line_int_cnt;
int lack_buf_cnt;
unsigned int buf_wake_up_cnt;
@@ -894,6 +895,9 @@ struct rkcif_device {
struct rkcif_err_state_work err_state_work;
struct rkcif_sensor_work sensor_work;
int resume_mode;
u32 nr_buf_size;
u32 share_mem_size;
u32 thunderboot_sensor_num;
int sensor_state;
};

View File

@@ -278,14 +278,14 @@ static void sditf_free_buf(struct sditf_priv *priv)
struct rkcif_device *cif_dev = priv->cif_dev;
if (priv->hdr_cfg.hdr_mode == HDR_X2) {
rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num);
rkcif_free_rx_buf(&cif_dev->stream[0], cif_dev->stream[0].rx_buf_num);
rkcif_free_rx_buf(&cif_dev->stream[1], cif_dev->stream[1].rx_buf_num);
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num);
rkcif_free_rx_buf(&cif_dev->stream[2], priv->buf_num);
rkcif_free_rx_buf(&cif_dev->stream[0], cif_dev->stream[0].rx_buf_num);
rkcif_free_rx_buf(&cif_dev->stream[1], cif_dev->stream[1].rx_buf_num);
rkcif_free_rx_buf(&cif_dev->stream[2], cif_dev->stream[2].rx_buf_num);
} else {
rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
rkcif_free_rx_buf(&cif_dev->stream[0], cif_dev->stream[0].rx_buf_num);
}
if (cif_dev->is_thunderboot) {
cif_dev->wait_line_cache = 0;
@@ -617,22 +617,26 @@ void sditf_change_to_online(struct sditf_priv *priv)
sditf_channel_enable(priv, 0);
sditf_channel_enable(priv, 1);
}
if (priv->hdr_cfg.hdr_mode == NO_HDR) {
rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
cif_dev->stream[0].is_line_wake_up = false;
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num);
cif_dev->stream[0].is_line_wake_up = false;
cif_dev->stream[1].is_line_wake_up = false;
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
rkcif_free_rx_buf(&cif_dev->stream[2], priv->buf_num);
cif_dev->stream[0].is_line_wake_up = false;
cif_dev->stream[1].is_line_wake_up = false;
cif_dev->stream[2].is_line_wake_up = false;
if (cif_dev->is_thunderboot) {
if (priv->hdr_cfg.hdr_mode == NO_HDR) {
rkcif_free_rx_buf(&cif_dev->stream[0], cif_dev->stream[0].rx_buf_num);
cif_dev->stream[0].is_line_wake_up = false;
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
rkcif_free_rx_buf(&cif_dev->stream[1], cif_dev->stream[1].rx_buf_num);
cif_dev->stream[0].is_line_wake_up = false;
cif_dev->stream[1].is_line_wake_up = false;
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
rkcif_free_rx_buf(&cif_dev->stream[2], cif_dev->stream[2].rx_buf_num);
cif_dev->stream[0].is_line_wake_up = false;
cif_dev->stream[1].is_line_wake_up = false;
cif_dev->stream[2].is_line_wake_up = false;
}
cif_dev->wait_line_cache = 0;
cif_dev->wait_line = 0;
cif_dev->wait_line_bak = 0;
cif_dev->is_thunderboot = false;
}
cif_dev->wait_line_cache = 0;
cif_dev->wait_line = 0;
cif_dev->wait_line_bak = 0;
}
void sditf_disable_immediately(struct sditf_priv *priv)
@@ -857,6 +861,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
if (!list_empty(&stream->rx_buf_head) &&
cif_dev->is_thunderboot &&
(!cif_dev->is_rtt_suspend) &&
(dbufs->type == BUF_SHORT ||
(dbufs->type != BUF_SHORT && (!dbufs->is_switch)))) {
spin_lock_irqsave(&cif_dev->buffree_lock, buffree_flags);

View File

@@ -50,6 +50,7 @@
#endif
#include <linux/uaccess.h>
#include <linux/cpuhotplug.h>
#include "fiq_debugger.h"
#include "fiq_debugger_priv.h"
@@ -148,10 +149,7 @@ static bool initial_debug_enable;
static bool initial_console_enable;
#endif
#ifdef CONFIG_FIQ_DEBUGGER_TRUST_ZONE
static struct fiq_debugger_state *state_tf;
#endif
static struct fiq_debugger_state *g_state;
static bool fiq_kgdb_enable;
static bool fiq_debugger_disable;
@@ -1076,7 +1074,7 @@ static void fiq_debugger_fiq(struct fiq_glue_handler *h,
#ifdef CONFIG_FIQ_DEBUGGER_TRUST_ZONE
void fiq_debugger_fiq(void *regs, u32 cpu)
{
struct fiq_debugger_state *state = state_tf;
struct fiq_debugger_state *state = g_state;
bool need_irq;
if (!state)
@@ -1443,6 +1441,18 @@ static int fiq_debugger_dev_resume(struct device *dev)
return 0;
}
static int fiq_debugger_cpu_offine_migrate_irq(unsigned int cpu)
{
if (g_state && cpu == g_state->current_cpu) {
unsigned int new_cpu = cpumask_any_but(cpu_online_mask, cpu);
if (new_cpu < nr_cpu_ids)
g_state->current_cpu = new_cpu;
}
return 0;
}
static int fiq_debugger_probe(struct platform_device *pdev)
{
int ret;
@@ -1450,6 +1460,7 @@ static int fiq_debugger_probe(struct platform_device *pdev)
struct fiq_debugger_state *state;
int fiq;
int uart_irq;
enum cpuhp_state cs = -1;
if (pdev->id >= MAX_FIQ_DEBUGGER_PORTS)
return -EINVAL;
@@ -1569,6 +1580,15 @@ static int fiq_debugger_probe(struct platform_device *pdev)
* can.
*/
enable_irq_wake(state->uart_irq);
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"soc/fiq_debugger",
NULL,
fiq_debugger_cpu_offine_migrate_irq);
if (ret < 0)
pr_err("%s: could not setup cpu offine handler\n", __func__);
else
cs = ret;
}
if (state->signal_irq >= 0) {
@@ -1599,10 +1619,6 @@ static int fiq_debugger_probe(struct platform_device *pdev)
if (state->no_sleep)
fiq_debugger_handle_wakeup(state);
#ifdef CONFIG_FIQ_DEBUGGER_TRUST_ZONE
state_tf = state;
#endif
if (pdata->uart_init) {
ret = pdata->uart_init(pdev);
if (ret)
@@ -1629,7 +1645,7 @@ console_out:
/* switch to cpu0 default */
fiq_debugger_switch_cpu(state, 0);
g_state = state;
return 0;
err_register_irq:
@@ -1640,6 +1656,8 @@ err_uart_init:
clk_disable(state->clk);
if (state->clk)
clk_put(state->clk);
if (cs >= 0)
cpuhp_remove_state_nocalls(cs);
wakeup_source_remove(&state->debugger_wake_src);
__pm_relax(&state->debugger_wake_src);
platform_set_drvdata(pdev, NULL);

View File

@@ -659,20 +659,68 @@ static int md_register_minidump_entry(char *name, u64 virt_addr,
return ret;
}
static int md_is_kernel_address(u64 addr)
static struct page *md_vmalloc_to_page(const void *vmalloc_addr)
{
unsigned long addr = (unsigned long) vmalloc_addr;
struct page *page = NULL;
pgd_t *pgd = pgd_offset_k(addr);
p4d_t *p4d;
pud_t *pud;
pmd_t *pmd;
pte_t *ptep, pte;
if (pgd_none(*pgd))
return NULL;
p4d = p4d_offset(pgd, addr);
if (p4d_none(*p4d))
return NULL;
pud = pud_offset(p4d, addr);
if (pud_none(*pud) || pud_bad(*pud))
return NULL;
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd) || pmd_bad(*pmd))
return NULL;
ptep = pte_offset_map(pmd, addr);
pte = *ptep;
if (pte_present(pte))
page = pte_page(pte);
pte_unmap(ptep);
return page;
}
static bool md_is_kernel_address(u64 addr)
{
u32 data;
u64 phys_addr = 0;
struct page *page;
if (addr < PAGE_OFFSET || addr > -4096UL)
return 0;
if (!is_ttbr1_addr(addr))
return false;
if (addr >= (u64)_text && addr < (u64)_end)
return 0;
return false;
if (__is_lm_address(addr)) {
phys_addr = virt_to_phys((void *)addr);
} else if (is_vmalloc_or_module_addr((const void *)addr)) {
page = md_vmalloc_to_page((const void *) addr);
if (page)
phys_addr = page_to_phys(page);
else
return false;
} else {
return false;
}
if (!md_is_ddr_address(phys_addr))
return false;
if (aarch64_insn_read((void *)addr, &data))
return 0;
return false;
else
return 1;
return true;
}
static int md_save_page(u64 addr, bool flush)
@@ -689,8 +737,8 @@ static int md_save_page(u64 addr, bool flush)
if (__is_lm_address(virt_addr)) {
phys_addr = virt_to_phys((void *)virt_addr);
} else if (virt_addr >= VMALLOC_START && virt_addr < VMALLOC_END) {
page = vmalloc_to_page((const void *) virt_addr);
} else if (is_vmalloc_or_module_addr((const void *)virt_addr)) {
page = md_vmalloc_to_page((const void *) virt_addr);
phys_addr = page_to_phys(page);
} else {
return -1;

View File

@@ -933,7 +933,7 @@ static ssize_t slab_owner_dump_size_read(struct file *file, char __user *ubuf,
{
char buf[100];
snprintf(buf, sizeof(buf), "%llu MB\n", md_slabowner_dump_size/SZ_1M);
snprintf(buf, sizeof(buf), "%lu MB\n", md_slabowner_dump_size/SZ_1M);
return simple_read_from_buffer(ubuf, count, offset, buf, strlen(buf));
}

View File

@@ -72,6 +72,8 @@ static bool md_init_done;
static void __iomem *md_elf_mem;
static resource_size_t md_elf_size;
static struct proc_dir_entry *proc_rk_minidump;
static bool md_is_ddr_address_default(u64 phys_addr);
bool (*md_is_ddr_address)(u64 virt_addr) = md_is_ddr_address_default;
/* Number of pending entries to be added in ToC regions */
static unsigned int pendings;
@@ -621,6 +623,22 @@ static const struct proc_ops rk_minidump_proc_ops = {
.proc_read = rk_minidump_read_elf,
};
static bool md_is_ddr_address_rk3588(u64 phys_addr)
{
/* peripheral address space */
if (phys_addr >= 0xf0000000 && phys_addr < 0x100000000)
return false;
/* DDR is up to 32GB */
if (phys_addr > 0x800000000)
return false;
return true;
}
static bool md_is_ddr_address_default(u64 phys_addr)
{
return true;
}
static int rk_minidump_driver_probe(struct platform_device *pdev)
{
unsigned int i;
@@ -689,6 +707,9 @@ static int rk_minidump_driver_probe(struct platform_device *pdev)
pr_info("Create /proc/rk_md/minidump fail...\n");
}
if (of_machine_is_compatible("rockchip,rk3588"))
md_is_ddr_address = md_is_ddr_address_rk3588;
/* Check global minidump support initialization */
if (!md_global_toc->md_toc_init) {
pr_err("System Minidump TOC not initialized\n");

View File

@@ -5,6 +5,7 @@ source "drivers/video/rockchip/rga3/Kconfig"
source "drivers/video/rockchip/rve/Kconfig"
source "drivers/video/rockchip/iep/Kconfig"
source "drivers/video/rockchip/mpp/Kconfig"
source "drivers/video/rockchip/mpp_osal/Kconfig"
source "drivers/video/rockchip/dvbm/Kconfig"
source "drivers/video/rockchip/vehicle/Kconfig"
source "drivers/video/rockchip/vtunnel/Kconfig"

View File

@@ -5,6 +5,7 @@ obj-$(CONFIG_ROCKCHIP_MULTI_RGA) += rga3/
obj-$(CONFIG_ROCKCHIP_RVE) += rve/
obj-$(CONFIG_IEP) += iep/
obj-$(CONFIG_ROCKCHIP_MPP_SERVICE) += mpp/
obj-$(CONFIG_ROCKCHIP_MPP_OSAL) += mpp_osal/
obj-$(CONFIG_ROCKCHIP_DVBM) += dvbm/
obj-$(CONFIG_VIDEO_REVERSE_IMAGE) += vehicle/
obj-$(CONFIG_ROCKCHIP_VIDEO_TUNNEL) += vtunnel/

View File

@@ -0,0 +1,8 @@
# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
config ROCKCHIP_MPP_OSAL
bool "mpp osal"
depends on CPU_RV1106
default y
help
rockchip mpp osal adapt for kmpp

View File

@@ -0,0 +1,2 @@
# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
obj-$(CONFIG_ROCKCHIP_MPP_OSAL) += mpp_osal.o

View File

@@ -0,0 +1,30 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2023 Rockchip Electronics Co., Ltd
*
*/
#include "mpp_osal.h"
struct device_node *mpp_dev_of_node(struct device *dev)
{
return dev_of_node(dev);
}
EXPORT_SYMBOL(mpp_dev_of_node);
void mpp_pm_relax(struct device *dev)
{
return pm_relax(dev);
}
EXPORT_SYMBOL(mpp_pm_relax);
void mpp_pm_stay_awake(struct device *dev)
{
return pm_stay_awake(dev);
}
EXPORT_SYMBOL(mpp_pm_stay_awake);
int mpp_device_init_wakeup(struct device *dev, bool enable)
{
return device_init_wakeup(dev, enable);
}
EXPORT_SYMBOL(mpp_device_init_wakeup);

View File

@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (c) 2023 Rockchip Electronics Co., Ltd
*
*/
#ifndef __ROCKCHIP_MPP_OSAL_H__
#define __ROCKCHIP_MPP_OSAL_H__
#include <linux/platform_device.h>
#include <linux/pm_wakeup.h>
struct device_node *mpp_dev_of_node(struct device *dev);
void mpp_pm_relax(struct device *dev);
void mpp_pm_stay_awake(struct device *dev);
int mpp_device_init_wakeup(struct device *dev, bool enable);
#endif

View File

@@ -71,4 +71,5 @@ static inline int rk_minidump_hardlock_notify(struct notifier_block *nb,
#endif
void rk_md_flush_dcache_area(void *addr, size_t len);
extern bool (*md_is_ddr_address)(u64 virt_addr);
#endif /* __RK_MINIDUMP_H */

View File

@@ -1994,6 +1994,8 @@ struct rkisp_thunderboot_resmem_head {
__u32 exp_time_reg[3];
__u32 exp_gain_reg[3];
__u32 exp_isp_dgain[3];
__u32 nr_buf_size;
__u32 share_mem_size;
} __attribute__ ((packed));
/**