From 682d7c7aff422bfbcaa5438e7d2771bbf78bf816 Mon Sep 17 00:00:00 2001 From: Wang Panzhenzhuan Date: Tue, 10 Dec 2024 16:12:11 +0800 Subject: [PATCH 01/51] media: i2c: add os05l10 camera driver Signed-off-by: Wang Panzhenzhuan Change-Id: I0cf41a250d1a1818c4b4cdd19a949a3fddd297d2 --- drivers/media/i2c/Kconfig | 11 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/os05l10.c | 1739 +++++++++++++++++++++++++++++++++++ 3 files changed, 1751 insertions(+) create mode 100644 drivers/media/i2c/os05l10.c diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index d3c0bc171f65..67a779ea612e 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1050,6 +1050,17 @@ config VIDEO_OS05A20 This is a Video4Linux2 sensor driver for the OmniVision OS05A20 camera. +config VIDEO_OS05L10 + tristate "OmniVision OS05L10 sensor support" + depends on I2C && VIDEO_DEV + depends on MEDIA_CAMERA_SUPPORT + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE + help + This is a Video4Linux2 sensor driver for the OmniVision + OS05L10 camera. + config VIDEO_OS08A20 tristate "OmniVision OS08A20 sensor support" depends on I2C && VIDEO_DEV diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 6a293413fb71..12cd075780b4 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -153,6 +153,7 @@ obj-$(CONFIG_VIDEO_OS03B10) += os03b10.o obj-$(CONFIG_VIDEO_OS04A10) += os04a10.o obj-$(CONFIG_VIDEO_OS04D10) += os04d10.o obj-$(CONFIG_VIDEO_OS05A20) += os05a20.o +obj-$(CONFIG_VIDEO_OS05L10) += os05l10.o obj-$(CONFIG_VIDEO_OS08A20) += os08a20.o obj-$(CONFIG_VIDEO_OTP_EEPROM) += otp_eeprom.o obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o diff --git a/drivers/media/i2c/os05l10.c b/drivers/media/i2c/os05l10.c new file mode 100644 index 000000000000..e0c2f4321d67 --- /dev/null +++ b/drivers/media/i2c/os05l10.c @@ -0,0 +1,1739 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * os05l10 driver + * + * Copyright (C) 2024 Rockchip Electronics Co., Ltd. + * + * V0.0X01.0X00 init sensor driver. + */ +//#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "otp_eeprom.h" + +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00) + +#ifndef V4L2_CID_DIGITAL_GAIN +#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN +#endif + +#define OS05L10_LANES 2 +#define OS05L10_BITS_PER_SAMPLE 10 +#define OS05L10_MIPI_FREQ_420MHZ 420000000U + +/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ +#define OS05L10_PIXEL_RATE 288000000 +#define OS05L10_XVCLK_FREQ 24000000 + +#define CHIP_ID 0x104c +#define OS05L10_REG_CHIP_ID_H 0x00 +#define OS05L10_REG_CHIP_ID_L 0x01 + +#define OS05L10_REG_SET_PAGE 0xfd +#define OS05L10_SET_PAGE_ZERO 0x00 + +#define OS05L10_REG_CTRL_MODE 0xa0 +#define OS05L10_MODE_SW_STANDBY 0x00 +#define OS05L10_MODE_STREAMING 0x01 + +#define OS05L10_REG_EXPOSURE_H 0x03 +#define OS05L10_REG_EXPOSURE_L 0x04 +#define OS05L10_FETCH_HIGH_BYTE_EXP(VAL) (((VAL) >> 8) & 0xFF) /* 8 Bits */ +#define OS05L10_FETCH_LOW_BYTE_EXP(VAL) ((VAL) & 0xFF) /* 8 Bits */ +#define OS05L10_EXPOSURE_MIN 4 +#define OS05L10_EXPOSURE_STEP 1 +#define OS05L10_VTS_MAX 0x1fff + +#define OS05L10_REG_AGAIN_H 0x25 +#define OS05L10_REG_AGAIN_L 0x24 +#define OS05L10_GAIN_MIN 0x10 +#define OS05L10_GAIN_MAX 0x1F8 +#define OS05L10_GAIN_STEP 1 +#define OS05L10_GAIN_DEFAULT 0x20 +#define OS05L10_FETCH_H_BYTE_GAIN(VAL) (((VAL) >> 8) & 0x1) /* 1 Bits */ +#define OS05L10_FETCH_L_BYTE_GAIN(VAL) ((VAL) & 0xFF) /* 8 Bits */ + +#define OS05L10_REG_TRIGGER 0x01 + +#define OS05L10_REG_VTS_H 0x05 +#define OS05L10_REG_VTS_L 0x06 + +#define OS05L10_REG_TEST_PATTERN 0x12 +#define OS05L10_TEST_PATTERN_ENABLE 0x01 +#define OS05L10_TEST_PATTERN_DISABLE 0x0 + +#define OS05L10_FLIP_MIRROR_REG 0x32 +#define MIRROR_BIT_MASK BIT(0) +#define FLIP_BIT_MASK BIT(1) + +#define REG_NULL 0xFF + +#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default" +#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep" + +#define OS05L10_NAME "os05l10" +#define OS05L10_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR10_1X10 + +/* use RK_OTP or old mode */ +#define RK_OTP +/* choose 2lane support full 30fps or 15fps */ +#define OS05L10_2LANE_30FPS + +static const char * const os05l10_supply_names[] = { + "dovdd", /* Digital I/O power */ + "dvdd", /* Digital core power */ + "avdd", /* Analog power */ +}; + +#define OS05L10_NUM_SUPPLIES ARRAY_SIZE(os05l10_supply_names) + +struct regval { + u8 addr; + u8 val; +}; + +struct os05l10_mode { + u32 width; + u32 height; + struct v4l2_fract max_fps; + u32 hts_def; + u32 vts_def; + u32 exp_def; + u32 mipi_freq_idx; + const struct regval *global_reg_list; + const struct regval *reg_list; + u32 vc[PAD_MAX]; +}; + +struct os05l10 { + struct i2c_client *client; + struct clk *xvclk; + struct gpio_desc *power_gpio; + struct gpio_desc *reset_gpio; + struct gpio_desc *pwdn_gpio; + struct regulator_bulk_data supplies[OS05L10_NUM_SUPPLIES]; + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_sleep; + struct v4l2_subdev subdev; + struct media_pad pad; + 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 *link_freq; + struct v4l2_ctrl *test_pattern; + struct v4l2_ctrl *h_flip; + struct v4l2_ctrl *v_flip; + struct mutex mutex; + bool streaming; + unsigned int lane_num; + unsigned int cfg_num; + unsigned int pixel_rate; + bool power_on; + const struct os05l10_mode *cur_mode; + u32 module_index; + const char *module_facing; + const char *module_name; + const char *len_name; + u32 Dgain_ratio; + struct otp_info *otp; + struct rkmodule_inf module_inf; + struct rkmodule_awb_cfg awb_cfg; +}; + +#define to_os05l10(sd) container_of(sd, struct os05l10, subdev) + +/* + * Xclk 24Mhz + */ +static const struct regval os05l10_global_regs_2lane[] = { + {REG_NULL, 0x00}, +}; + +/* + * Input clock frequency: 24MHz + * mipi_datarate per lane 840Mbps + * hts = 400*8, vts=1750 + * pclk=168M row_clk=21M + * Image output size: 2880x 1620 + * frame rate = 21M/400/1750 = 30fps + */ +static const struct regval os05l10_2880x1620_regs_2lane[] = { + {0xfd, 0x00}, + {0x20, 0x00}, + {0xfd, 0x00}, + {0x20, 0x2b}, + {0xe7, 0x03}, + {0xe7, 0x00}, + {0xfd, 0x00}, + {0x21, 0x06}, + {0x14, 0x8c}, + {0x18, 0x61}, + {0x19, 0x80}, + {0x1a, 0x06}, + {0x1b, 0x69}, + {0x1c, 0x04}, + {0x1d, 0x02}, + {0xfd, 0x00}, + {0x21, 0x00}, + + {0xfd, 0x0f}, + {0x01, 0xe6}, + {0x07, 0x0f}, + {0x08, 0xf0}, + {0x0f, 0x08}, + {0x15, 0x28}, + {0x16, 0x11}, + {0x20, 0x06}, + {0x2e, 0x1c}, + {0x2f, 0x3d}, + {0x30, 0x77}, + {0x31, 0xe5}, + {0x0b, 0x01}, + {0x13, 0x22}, + {0x14, 0xbc}, + {0x2d, 0x0a}, + {0x17, 0x3e}, + {0x1b, 0xe6}, + {0x1c, 0x99}, + {0x1d, 0x99}, + {0x1e, 0x55}, + {0xfd, 0x01}, + {0x02, 0x00}, + {0x03, 0x02}, + {0x04, 0x04}, + {0x06, 0x5c}, + {0x24, 0x80}, + {0x21, 0x00}, + {0x22, 0x40}, + {0x31, 0x00}, + {0x33, 0x03}, + {0x40, 0x30}, + {0x41, 0x0c}, + {0x43, 0x44}, + {0x44, 0x0b}, + {0x46, 0x01}, + {0x48, 0x08}, + {0x4c, 0x10}, + {0x50, 0x0a}, + {0x51, 0x08}, + {0x52, 0x08}, + {0x53, 0x0a}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x57, 0x92}, + {0x58, 0x00}, + {0x59, 0x05}, + {0x5a, 0x05}, + {0x5b, 0x00}, + {0x5c, 0x0b}, + {0x5e, 0x08}, + {0x66, 0x0d}, + {0x69, 0x0d}, + {0x76, 0x0e}, + {0x7a, 0x00}, + {0x7c, 0x03}, + {0x83, 0x03}, + {0x84, 0x25}, + {0x85, 0x03}, + {0x87, 0x03}, + {0x90, 0x33}, + {0x91, 0x1e}, + {0x92, 0x15}, + {0x93, 0x16}, + {0x94, 0x08}, + {0x95, 0x33}, + {0x9c, 0x03}, + {0x9d, 0x13}, + {0x9e, 0x03}, + {0xa0, 0x13}, + {0xa4, 0x01}, + {0xa5, 0x01}, + {0xa7, 0x01}, + {0xc0, 0x09}, + {0xc1, 0x38}, + {0xc8, 0x1f}, + {0xd7, 0x11}, + {0xd9, 0x1c}, + {0xd8, 0x1f}, + {0xda, 0x2f}, + {0xdb, 0x10}, + {0xdd, 0x1b}, + {0xdc, 0x1e}, + {0xde, 0x2d}, + {0xed, 0x33}, + {0xee, 0x33}, + {0x01, 0x01}, + {0xfd, 0x02}, + {0x9a, 0x33}, + {0x05, 0x01}, + {0x0b, 0x0c}, + {0x0c, 0x0f}, + {0xfd, 0x01}, + {0x01, 0x01}, + {0xfd, 0x04}, + {0x19, 0x3f}, + {0x12, 0x00}, + {0xf3, 0x00}, + {0xfd, 0x07}, + {0x10, 0xf0}, + {0x42, 0x00}, + {0x43, 0x76}, + {0x44, 0x00}, + {0x45, 0x76}, + {0x46, 0x00}, + {0x47, 0x76}, + {0x48, 0x00}, + {0x49, 0x76}, + {0xb3, 0x02}, + {0xb4, 0x20}, + {0xb7, 0x02}, + {0xb8, 0x20}, + {0xc5, 0x3a}, + {0xc9, 0x3a}, + {0xcd, 0x3a}, + {0xc6, 0x2b}, + {0xca, 0x2b}, + {0xce, 0x2b}, + {0xc3, 0x0a}, + {0xc7, 0x0a}, + {0xcb, 0x0a}, + {0xc4, 0x12}, + {0xc8, 0x12}, + {0xcc, 0x12}, + {0xcf, 0x11}, + {0xd3, 0x11}, + {0xd7, 0x11}, + {0xd0, 0x0e}, + {0xd4, 0x0e}, + {0xd8, 0x0e}, + {0xbb, 0x7f}, + {0xd1, 0x0f}, + {0xd5, 0x0f}, + {0xd9, 0x0f}, + {0xd2, 0x0a}, + {0xd6, 0x0a}, + {0xda, 0x0a}, + {0xbc, 0x3f}, + {0xfd, 0x03}, + {0x85, 0x03}, + {0x9d, 0x0f}, + {0xba, 0x06}, + {0xfd, 0x01}, + {0xfd, 0x02}, + {0xa1, 0x04}, + {0xa3, 0x54}, + {0xa5, 0x04}, + {0xa7, 0x40}, + {0xfd, 0x00}, + {0x8e, 0x0b}, + {0x8f, 0x40}, + {0x90, 0x06}, + {0x91, 0x54}, + {0x94, 0x08}, + {0x95, 0x09}, + {0x99, 0x08}, + {0x9c, 0x20}, + {0xa4, 0x0c}, + {0x9d, 0x01}, + {0xa5, 0xff}, + {0xa1, 0x04}, + {0xb7, 0x02}, //mipi clk mode:0x00 continue; 0x02 no continue + + {0xc1, 0xee}, + {0xc5, 0x50}, + {0xc4, 0x01}, + {0xa0, 0x00}, + {0xfd, 0x01}, + {0xfd, 0x01}, + {0x01, 0x31}, + {0xfd, 0x00}, + {0x20, 0x1f}, + {0xfd, 0x01}, + {0xfd, 0x01}, + {REG_NULL, 0x00}, +}; + +static const struct os05l10_mode supported_modes_2lane[] = { + { + .width = 2880, + .height = 1620, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0600, + .hts_def = 0x0190 * 8, + .vts_def = 0x06d6, + .mipi_freq_idx = 0, + .global_reg_list = os05l10_global_regs_2lane, + .reg_list = os05l10_2880x1620_regs_2lane, + .vc[PAD0] = 0, + }, +}; + +static const struct os05l10_mode *supported_modes; + +static const s64 link_freq_menu_items[] = { + OS05L10_MIPI_FREQ_420MHZ, +}; + +static const char * const os05l10_test_pattern_menu[] = { + "Disabled", + "ColorBar" +}; + +/* Write registers up to 4 at a time */ +static int os05l10_write_reg(struct i2c_client *client, u8 reg, u8 val) +{ + struct i2c_msg msg; + u8 buf[2]; + int ret; + + buf[0] = reg & 0xFF; + buf[1] = val; + + msg.addr = client->addr; + msg.flags = client->flags; + msg.buf = buf; + msg.len = sizeof(buf); + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret >= 0) + return 0; + + dev_err(&client->dev, + "os05l10 write reg(0x%x val:0x%x) failed !\n", reg, val); + + return ret; +} + +static int os05l10_write_array(struct i2c_client *client, + const struct regval *regs) +{ + u32 i = 0; + int ret = 0; + + for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) + ret = os05l10_write_reg(client, regs[i].addr, regs[i].val); + + return ret; +} + +/* Read registers up to 4 at a time */ +static int os05l10_read_reg(struct i2c_client *client, u8 reg, u8 *val) +{ + struct i2c_msg msg[2]; + u8 buf[1]; + int ret; + + buf[0] = reg & 0xFF; + + msg[0].addr = client->addr; + msg[0].flags = client->flags; + msg[0].buf = buf; + msg[0].len = sizeof(buf); + + msg[1].addr = client->addr; + msg[1].flags = client->flags | I2C_M_RD; + msg[1].buf = buf; + msg[1].len = 1; + + ret = i2c_transfer(client->adapter, msg, 2); + if (ret >= 0) { + *val = buf[0]; + return 0; + } + + dev_err(&client->dev, + "os05l10 read reg:0x%x failed !\n", reg); + + return ret; +} + +static int os05l10_get_reso_dist(const struct os05l10_mode *mode, + struct v4l2_mbus_framefmt *framefmt) +{ + return abs(mode->width - framefmt->width) + + abs(mode->height - framefmt->height); +} + +static const struct os05l10_mode * +os05l10_find_best_fit(struct os05l10 *os05l10, + struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *framefmt = &fmt->format; + int dist; + int cur_best_fit = 0; + int cur_best_fit_dist = -1; + unsigned int i; + + for (i = 0; i < os05l10->cfg_num; i++) { + dist = os05l10_get_reso_dist(&supported_modes[i], framefmt); + if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) { + cur_best_fit_dist = dist; + cur_best_fit = i; + } + } + + return &supported_modes[cur_best_fit]; +} + +static int os05l10_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + const struct os05l10_mode *mode; + s64 h_blank, vblank_def; + + mutex_lock(&os05l10->mutex); + + mode = os05l10_find_best_fit(os05l10, fmt); + fmt->format.code = OS05L10_MEDIA_BUS_FMT; + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.field = V4L2_FIELD_NONE; + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; +#else + mutex_unlock(&os05l10->mutex); + return -ENOTTY; +#endif + } else { + os05l10->cur_mode = mode; + h_blank = mode->hts_def - mode->width; + __v4l2_ctrl_modify_range(os05l10->hblank, h_blank, + h_blank, 1, h_blank); + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(os05l10->vblank, vblank_def, + OS05L10_VTS_MAX - mode->height, + 1, vblank_def); + __v4l2_ctrl_s_ctrl(os05l10->vblank, vblank_def); + __v4l2_ctrl_s_ctrl(os05l10->link_freq, mode->mipi_freq_idx); + } + + mutex_unlock(&os05l10->mutex); + + return 0; +} + +static int os05l10_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + const struct os05l10_mode *mode = os05l10->cur_mode; + + mutex_lock(&os05l10->mutex); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + fmt->format = *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); +#else + mutex_unlock(&os05l10->mutex); + return -ENOTTY; +#endif + } else { + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.code = OS05L10_MEDIA_BUS_FMT; + fmt->format.field = V4L2_FIELD_NONE; + } + mutex_unlock(&os05l10->mutex); + + return 0; +} + +static int os05l10_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index != 0) + return -EINVAL; + code->code = OS05L10_MEDIA_BUS_FMT; + + return 0; +} + +static int os05l10_enum_frame_sizes(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + + if (fse->index >= os05l10->cfg_num) + return -EINVAL; + + if (fse->code != OS05L10_MEDIA_BUS_FMT) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = supported_modes[fse->index].width; + fse->max_height = supported_modes[fse->index].height; + fse->min_height = supported_modes[fse->index].height; + + return 0; +} + +static int os05l10_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + const struct os05l10_mode *mode = os05l10->cur_mode; + + fi->interval = mode->max_fps; + + return 0; +} + +static void os05l10_get_otp(struct otp_info *otp, + struct rkmodule_inf *inf) +{ + u32 i, j; + u32 w, h; + + /* awb */ + if (otp->awb_data.flag) { + inf->awb.flag = 1; + inf->awb.r_value = otp->awb_data.r_ratio; + inf->awb.b_value = otp->awb_data.b_ratio; + inf->awb.gr_value = otp->awb_data.g_ratio; + inf->awb.gb_value = 0x0; + + inf->awb.golden_r_value = otp->awb_data.r_golden; + inf->awb.golden_b_value = otp->awb_data.b_golden; + inf->awb.golden_gr_value = otp->awb_data.g_golden; + inf->awb.golden_gb_value = 0x0; + } + + /* lsc */ + if (otp->lsc_data.flag) { + inf->lsc.flag = 1; + inf->lsc.width = otp->basic_data.size.width; + inf->lsc.height = otp->basic_data.size.height; + inf->lsc.table_size = otp->lsc_data.table_size; + + for (i = 0; i < 289; i++) { + inf->lsc.lsc_r[i] = (otp->lsc_data.data[i * 2] << 8) | + otp->lsc_data.data[i * 2 + 1]; + inf->lsc.lsc_gr[i] = (otp->lsc_data.data[i * 2 + 578] << 8) | + otp->lsc_data.data[i * 2 + 579]; + inf->lsc.lsc_gb[i] = (otp->lsc_data.data[i * 2 + 1156] << 8) | + otp->lsc_data.data[i * 2 + 1157]; + inf->lsc.lsc_b[i] = (otp->lsc_data.data[i * 2 + 1734] << 8) | + otp->lsc_data.data[i * 2 + 1735]; + } + } + + /* pdaf */ + if (otp->pdaf_data.flag) { + inf->pdaf.flag = 1; + inf->pdaf.gainmap_width = otp->pdaf_data.gainmap_width; + inf->pdaf.gainmap_height = otp->pdaf_data.gainmap_height; + inf->pdaf.pd_offset = otp->pdaf_data.pd_offset; + inf->pdaf.dcc_mode = otp->pdaf_data.dcc_mode; + inf->pdaf.dcc_dir = otp->pdaf_data.dcc_dir; + inf->pdaf.dccmap_width = otp->pdaf_data.dccmap_width; + inf->pdaf.dccmap_height = otp->pdaf_data.dccmap_height; + w = otp->pdaf_data.gainmap_width; + h = otp->pdaf_data.gainmap_height; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + inf->pdaf.gainmap[i * w + j] = + (otp->pdaf_data.gainmap[(i * w + j) * 2] << 8) | + otp->pdaf_data.gainmap[(i * w + j) * 2 + 1]; + } + } + w = otp->pdaf_data.dccmap_width; + h = otp->pdaf_data.dccmap_height; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + inf->pdaf.dccmap[i * w + j] = + (otp->pdaf_data.dccmap[(i * w + j) * 2] << 8) | + otp->pdaf_data.dccmap[(i * w + j) * 2 + 1]; + } + } + } + + /* af */ + if (otp->af_data.flag) { + inf->af.flag = 1; + inf->af.dir_cnt = 1; + inf->af.af_otp[0].vcm_start = otp->af_data.af_inf; + inf->af.af_otp[0].vcm_end = otp->af_data.af_macro; + inf->af.af_otp[0].vcm_dir = 0; + } + +} + +static void os05l10_get_module_inf(struct os05l10 *os05l10, + struct rkmodule_inf *inf) +{ + struct otp_info *otp = os05l10->otp; + + strscpy(inf->base.sensor, + OS05L10_NAME, + sizeof(inf->base.sensor)); + strscpy(inf->base.module, + os05l10->module_name, + sizeof(inf->base.module)); + strscpy(inf->base.lens, + os05l10->len_name, + sizeof(inf->base.lens)); + if (otp) + os05l10_get_otp(otp, inf); +} + +static void os05l10_set_module_inf(struct os05l10 *os05l10, + struct rkmodule_awb_cfg *cfg) +{ + mutex_lock(&os05l10->mutex); + memcpy(&os05l10->awb_cfg, cfg, sizeof(*cfg)); + mutex_unlock(&os05l10->mutex); +} + +static int os05l10_get_channel_info(struct os05l10 *os05l10, struct rkmodule_channel_info *ch_info) +{ + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) + return -EINVAL; + ch_info->vc = os05l10->cur_mode->vc[ch_info->index]; + ch_info->width = os05l10->cur_mode->width; + ch_info->height = os05l10->cur_mode->height; + ch_info->bus_fmt = OS05L10_MEDIA_BUS_FMT; + return 0; +} + +static long os05l10_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + long ret = 0; + u32 stream = 0; + struct rkmodule_channel_info *ch_info; + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + os05l10_get_module_inf(os05l10, (struct rkmodule_inf *)arg); + break; + case RKMODULE_AWB_CFG: + os05l10_set_module_inf(os05l10, (struct rkmodule_awb_cfg *)arg); + break; + case RKMODULE_SET_QUICK_STREAM: + + stream = *((u32 *)arg); + if (stream) { + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + 0x01); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_CTRL_MODE, + OS05L10_MODE_STREAMING); + } else { + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + 0x01); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_CTRL_MODE, + OS05L10_MODE_SW_STANDBY); + } + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = (struct rkmodule_channel_info *)arg; + ret = os05l10_get_channel_info(os05l10, ch_info); + break; + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static long os05l10_compat_ioctl32(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + void __user *up = compat_ptr(arg); + struct rkmodule_inf *inf; + struct rkmodule_awb_cfg *cfg; + long ret = 0; + u32 stream = 0; + struct rkmodule_channel_info *ch_info; + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + inf = kzalloc(sizeof(*inf), GFP_KERNEL); + if (!inf) { + ret = -ENOMEM; + return ret; + } + + ret = os05l10_ioctl(sd, cmd, inf); + if (!ret) { + ret = copy_to_user(up, inf, sizeof(*inf)); + if (ret) + ret = -EFAULT; + } + kfree(inf); + break; + case RKMODULE_AWB_CFG: + cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) { + ret = -ENOMEM; + return ret; + } + + ret = copy_from_user(cfg, up, sizeof(*cfg)); + if (!ret) + ret = os05l10_ioctl(sd, cmd, cfg); + else + ret = -EFAULT; + kfree(cfg); + break; + case RKMODULE_SET_QUICK_STREAM: + ret = copy_from_user(&stream, up, sizeof(u32)); + if (!ret) + ret = os05l10_ioctl(sd, cmd, &stream); + else + ret = -EFAULT; + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); + if (!ch_info) { + ret = -ENOMEM; + return ret; + } + + ret = os05l10_ioctl(sd, cmd, ch_info); + if (!ret) { + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); + if (ret) + ret = -EFAULT; + } + kfree(ch_info); + break; + default: + ret = -ENOTTY; + break; + } + + return ret; +} +#endif + +static int __os05l10_start_stream(struct os05l10 *os05l10) +{ + int ret; + + ret = os05l10_write_array(os05l10->client, os05l10->cur_mode->reg_list); + if (ret) + return ret; + + /* In case these controls are set before streaming */ + mutex_unlock(&os05l10->mutex); + ret = v4l2_ctrl_handler_setup(&os05l10->ctrl_handler); + mutex_lock(&os05l10->mutex); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + OS05L10_SET_PAGE_ZERO); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_CTRL_MODE, + OS05L10_MODE_STREAMING); + + return ret; +} + +static int __os05l10_stop_stream(struct os05l10 *os05l10) +{ + int ret; + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + OS05L10_SET_PAGE_ZERO); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_CTRL_MODE, + OS05L10_MODE_STREAMING); + + + return ret; +} + +static int os05l10_s_stream(struct v4l2_subdev *sd, int on) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + struct i2c_client *client = os05l10->client; + int ret = 0; + + dev_info(&client->dev, "%s: on: %d, %dx%d@%d\n", __func__, on, + os05l10->cur_mode->width, + os05l10->cur_mode->height, + DIV_ROUND_CLOSEST(os05l10->cur_mode->max_fps.denominator, + os05l10->cur_mode->max_fps.numerator)); + + mutex_lock(&os05l10->mutex); + on = !!on; + if (on == os05l10->streaming) + goto unlock_and_return; + + if (on) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + ret = __os05l10_start_stream(os05l10); + if (ret) { + v4l2_err(sd, "start stream failed while write regs\n"); + pm_runtime_put(&client->dev); + goto unlock_and_return; + } + } else { + __os05l10_stop_stream(os05l10); + pm_runtime_put(&client->dev); + } + + os05l10->streaming = on; + +unlock_and_return: + mutex_unlock(&os05l10->mutex); + + return ret; +} + +static int os05l10_s_power(struct v4l2_subdev *sd, int on) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + struct i2c_client *client = os05l10->client; + const struct os05l10_mode *mode = os05l10->cur_mode; + int ret = 0; + + dev_info(&client->dev, "%s(%d) on(%d)\n", __func__, __LINE__, on); + mutex_lock(&os05l10->mutex); + + /* If the power state is not modified - no work to do. */ + if (os05l10->power_on == !!on) + goto unlock_and_return; + + if (on) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + ret = os05l10_write_array(os05l10->client, mode->global_reg_list); + if (ret) { + v4l2_err(sd, "could not set init registers\n"); + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + os05l10->power_on = true; + } else { + pm_runtime_put(&client->dev); + os05l10->power_on = false; + } + +unlock_and_return: + mutex_unlock(&os05l10->mutex); + + return ret; +} + +/* Calculate the delay in us by clock rate and clock cycles */ +static inline u32 os05l10_cal_delay(u32 cycles) +{ + return DIV_ROUND_UP(cycles, OS05L10_XVCLK_FREQ / 1000 / 1000); +} + +static int os05l10_enable_regulators(struct os05l10 *os05l10, + struct regulator_bulk_data *consumers) +{ + int i, j; + int ret = 0; + struct device *dev = &os05l10->client->dev; + int num_consumers = OS05L10_NUM_SUPPLIES; + + for (i = 0; i < num_consumers; i++) { + + ret = regulator_enable(consumers[i].consumer); + if (ret < 0) { + dev_err(dev, "Failed to enable regulator: %s\n", + consumers[i].supply); + goto err; + } + } + return 0; +err: + for (j = 0; j < i; j++) + regulator_disable(consumers[j].consumer); + + return ret; +} + +static int __os05l10_power_on(struct os05l10 *os05l10) +{ + int ret; + struct device *dev = &os05l10->client->dev; + + if (!IS_ERR(os05l10->power_gpio)) + gpiod_set_value_cansleep(os05l10->power_gpio, 1); + + usleep_range(1000, 2000); + + if (!IS_ERR_OR_NULL(os05l10->pins_default)) { + ret = pinctrl_select_state(os05l10->pinctrl, + os05l10->pins_default); + if (ret < 0) + dev_err(dev, "could not set pins\n"); + } + ret = clk_set_rate(os05l10->xvclk, OS05L10_XVCLK_FREQ); + if (ret < 0) + dev_warn(dev, "Failed to set xvclk rate (24MHz)\n"); + if (clk_get_rate(os05l10->xvclk) != OS05L10_XVCLK_FREQ) + dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); + + if (!IS_ERR(os05l10->reset_gpio)) + gpiod_set_value_cansleep(os05l10->reset_gpio, 0); + + ret = os05l10_enable_regulators(os05l10, os05l10->supplies); + if (ret < 0) { + dev_err(dev, "Failed to enable regulators\n"); + goto disable_clk; + } + + ret = clk_prepare_enable(os05l10->xvclk); + if (ret < 0) { + dev_err(dev, "Failed to enable xvclk\n"); + return ret; + } + + usleep_range(1000, 1100); + if (!IS_ERR(os05l10->pwdn_gpio)) + gpiod_set_value_cansleep(os05l10->pwdn_gpio, 1); + + /*delay from dvdd stable to sensor XSHUTDN pull up*/ + usleep_range(5000, 5500); + if (!IS_ERR(os05l10->reset_gpio)) + gpiod_set_value_cansleep(os05l10->reset_gpio, 1); + + /*delay from XSHUTDN pull up to SCCB initialization*/ + usleep_range(8000, 8500); + + return 0; + +disable_clk: + clk_disable_unprepare(os05l10->xvclk); + + return ret; +} + +static void __os05l10_power_off(struct os05l10 *os05l10) +{ + int ret; + + if (!IS_ERR(os05l10->pwdn_gpio)) + gpiod_set_value_cansleep(os05l10->pwdn_gpio, 1); + + if (!IS_ERR(os05l10->reset_gpio)) + gpiod_set_value_cansleep(os05l10->reset_gpio, 1); + + clk_disable_unprepare(os05l10->xvclk); + if (!IS_ERR_OR_NULL(os05l10->pins_sleep)) { + ret = pinctrl_select_state(os05l10->pinctrl, + os05l10->pins_sleep); + if (ret < 0) + dev_dbg(&os05l10->client->dev, "could not set pins\n"); + } + if (!IS_ERR(os05l10->power_gpio)) + gpiod_set_value_cansleep(os05l10->power_gpio, 0); + + regulator_bulk_disable(OS05L10_NUM_SUPPLIES, os05l10->supplies); +} + +static int __maybe_unused os05l10_runtime_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct os05l10 *os05l10 = to_os05l10(sd); + + return __os05l10_power_on(os05l10); +} + +static int __maybe_unused os05l10_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct os05l10 *os05l10 = to_os05l10(sd); + + __os05l10_power_off(os05l10); + + return 0; +} + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int os05l10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->state, 0); + const struct os05l10_mode *def_mode = &supported_modes[0]; + + mutex_lock(&os05l10->mutex); + /* Initialize try_fmt */ + try_fmt->width = def_mode->width; + try_fmt->height = def_mode->height; + try_fmt->code = OS05L10_MEDIA_BUS_FMT; + try_fmt->field = V4L2_FIELD_NONE; + + mutex_unlock(&os05l10->mutex); + /* No crop or compose */ + + return 0; +} +#endif + +static int os05l10_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + + if (fie->index >= os05l10->cfg_num) + return -EINVAL; + + fie->code = OS05L10_MEDIA_BUS_FMT; + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + +static int os05l10_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, + struct v4l2_mbus_config *config) +{ + struct os05l10 *sensor = to_os05l10(sd); + struct device *dev = &sensor->client->dev; + + dev_info(dev, "%s(%d) enter!\n", __func__, __LINE__); + + if (2 == sensor->lane_num) { + config->type = V4L2_MBUS_CSI2_DPHY; + config->bus.mipi_csi2.num_data_lanes = sensor->lane_num; + } else { + dev_err(&sensor->client->dev, + "unsupported lane_num(%d)\n", sensor->lane_num); + } + return 0; +} + +static const struct dev_pm_ops os05l10_pm_ops = { + SET_RUNTIME_PM_OPS(os05l10_runtime_suspend, + os05l10_runtime_resume, NULL) +}; + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops os05l10_internal_ops = { + .open = os05l10_open, +}; +#endif + +static const struct v4l2_subdev_core_ops os05l10_core_ops = { + .s_power = os05l10_s_power, + .ioctl = os05l10_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = os05l10_compat_ioctl32, +#endif +}; + +static const struct v4l2_subdev_video_ops os05l10_video_ops = { + .s_stream = os05l10_s_stream, + .g_frame_interval = os05l10_g_frame_interval, +}; + +static const struct v4l2_subdev_pad_ops os05l10_pad_ops = { + .enum_mbus_code = os05l10_enum_mbus_code, + .enum_frame_size = os05l10_enum_frame_sizes, + .enum_frame_interval = os05l10_enum_frame_interval, + .get_fmt = os05l10_get_fmt, + .set_fmt = os05l10_set_fmt, + .get_mbus_config = os05l10_g_mbus_config, +}; + +static const struct v4l2_subdev_ops os05l10_subdev_ops = { + .core = &os05l10_core_ops, + .video = &os05l10_video_ops, + .pad = &os05l10_pad_ops, +}; + +static int os05l10_set_exposure_reg(struct os05l10 *os05l10, u32 exposure) +{ + int ret = 0; + u32 cal_shutter = 0; + + cal_shutter = exposure >> 1; + cal_shutter = cal_shutter << 1; + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, 0x01); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_EXPOSURE_H, + OS05L10_FETCH_HIGH_BYTE_EXP(cal_shutter)); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_EXPOSURE_L, + OS05L10_FETCH_LOW_BYTE_EXP(cal_shutter)); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TRIGGER, 0x01); + + return ret; +} + +static int os05l10_set_gain_reg(struct os05l10 *os05l10, u32 a_gain) +{ + int ret = 0; + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, 0x01); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_AGAIN_H, + OS05L10_FETCH_H_BYTE_GAIN(a_gain)); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_AGAIN_L, + OS05L10_FETCH_L_BYTE_GAIN(a_gain)); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TRIGGER, 0x01); + + return ret; +} + +static int os05l10__enable_test_pattern(struct os05l10 *os05l10, u32 pattern) +{ + u32 ret; + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, 0x04); + + if (pattern) { + ret |= os05l10_write_reg(os05l10->client, + 0xF3, 0x02); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TEST_PATTERN, 0x01); + } else { + ret |= os05l10_write_reg(os05l10->client, + 0xF3, 0x00); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TEST_PATTERN, 0x00); + } + + return ret; +} + +static int os05l10_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct os05l10 *os05l10 = container_of(ctrl->handler, + struct os05l10, ctrl_handler); + struct i2c_client *client = os05l10->client; + s64 max; + int ret = 0; + s32 temp; + u8 val = 0; + + /* Propagate change of current control to all related controls */ + switch (ctrl->id) { + case V4L2_CID_VBLANK: + /* Update max exposure while meeting expected vblanking */ + max = os05l10->cur_mode->height + ctrl->val - 4; + __v4l2_ctrl_modify_range(os05l10->exposure, + os05l10->exposure->minimum, max, + os05l10->exposure->step, + os05l10->exposure->default_value); + break; + } + + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + /* 4 least significant bits of expsoure are fractional part */ + dev_dbg(&client->dev, "set exposure value 0x%x\n", ctrl->val); + ret = os05l10_set_exposure_reg(os05l10, ctrl->val); + break; + case V4L2_CID_ANALOGUE_GAIN: + dev_dbg(&client->dev, "set analog gain value 0x%x\n", ctrl->val); + ret = os05l10_set_gain_reg(os05l10, ctrl->val); + break; + case V4L2_CID_VBLANK: + dev_dbg(&client->dev, "set vb value 0x%x\n", ctrl->val); + /* VB = VTS - height -38, */ + temp = ctrl->val + os05l10->cur_mode->height - 1620 - 38; + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + 0x01); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_VTS_H, + (temp >> 8) & 0xff); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_VTS_L, + temp & 0xff); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TRIGGER, + 0x01); + break; + case V4L2_CID_TEST_PATTERN: + ret = os05l10__enable_test_pattern(os05l10, ctrl->val); + break; + case V4L2_CID_HFLIP: + dev_info(&client->dev, "set mirror value 0x%x\n", ctrl->val); + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + 0x01); + ret |= os05l10_read_reg(client, OS05L10_FLIP_MIRROR_REG, &val); + if (ctrl->val) + val |= MIRROR_BIT_MASK; + else + val &= ~MIRROR_BIT_MASK; + ret |= os05l10_write_reg(os05l10->client, + OS05L10_FLIP_MIRROR_REG, + val); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TRIGGER, + 0x01); + break; + case V4L2_CID_VFLIP: + dev_info(&client->dev, "set flip value 0x%x\n", ctrl->val); + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + 0x01); + ret |= os05l10_read_reg(client, OS05L10_FLIP_MIRROR_REG, &val); + if (ctrl->val) + val |= FLIP_BIT_MASK; + else + val &= ~FLIP_BIT_MASK; + ret |= os05l10_write_reg(os05l10->client, + OS05L10_FLIP_MIRROR_REG, + val); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TRIGGER, + 0x01); + break; + default: + dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", + __func__, ctrl->id, ctrl->val); + break; + } + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops os05l10_ctrl_ops = { + .s_ctrl = os05l10_set_ctrl, +}; + +static int os05l10_initialize_controls(struct os05l10 *os05l10) +{ + const struct os05l10_mode *mode; + struct v4l2_ctrl_handler *handler; + s64 exposure_max, vblank_def; + u32 h_blank; + int ret; + + handler = &os05l10->ctrl_handler; + mode = os05l10->cur_mode; + ret = v4l2_ctrl_handler_init(handler, 8); + if (ret) + return ret; + handler->lock = &os05l10->mutex; + + os05l10->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(link_freq_menu_items) - 1, 0, + link_freq_menu_items); + v4l2_ctrl_s_ctrl(os05l10->link_freq, mode->mipi_freq_idx); + + v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, + 0, os05l10->pixel_rate, 1, os05l10->pixel_rate); + + h_blank = mode->hts_def - mode->width; + os05l10->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, + h_blank, h_blank, 1, h_blank); + if (os05l10->hblank) + os05l10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + vblank_def = mode->vts_def - mode->height; + os05l10->vblank = v4l2_ctrl_new_std(handler, &os05l10_ctrl_ops, + V4L2_CID_VBLANK, vblank_def, + OS05L10_VTS_MAX - mode->height, + 1, vblank_def); + + exposure_max = mode->vts_def - 4; + os05l10->exposure = v4l2_ctrl_new_std(handler, &os05l10_ctrl_ops, + V4L2_CID_EXPOSURE, OS05L10_EXPOSURE_MIN, + exposure_max, OS05L10_EXPOSURE_STEP, + mode->exp_def); + + os05l10->anal_gain = v4l2_ctrl_new_std(handler, &os05l10_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, OS05L10_GAIN_MIN, + OS05L10_GAIN_MAX, OS05L10_GAIN_STEP, + OS05L10_GAIN_DEFAULT); + + os05l10->test_pattern = v4l2_ctrl_new_std_menu_items(handler, + &os05l10_ctrl_ops, V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(os05l10_test_pattern_menu) - 1, + 0, 0, os05l10_test_pattern_menu); + + os05l10->h_flip = v4l2_ctrl_new_std(handler, &os05l10_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + + os05l10->v_flip = v4l2_ctrl_new_std(handler, &os05l10_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + if (handler->error) { + ret = handler->error; + dev_err(&os05l10->client->dev, + "Failed to init controls(%d)\n", ret); + goto err_free_handler; + } + + os05l10->subdev.ctrl_handler = handler; + + return 0; + +err_free_handler: + v4l2_ctrl_handler_free(handler); + + return ret; +} + +static int os05l10_check_sensor_id(struct os05l10 *os05l10, + struct i2c_client *client) +{ + struct device *dev = &os05l10->client->dev; + u16 id = 0; + u8 reg_H = 0; + u8 reg_L = 0; + int ret; + + ret = os05l10_read_reg(client, OS05L10_REG_CHIP_ID_H, ®_H); + ret |= os05l10_read_reg(client, OS05L10_REG_CHIP_ID_L, ®_L); + id = ((reg_H << 8) & 0xff00) | (reg_L & 0xff); + if (id != CHIP_ID) { + dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret); + //return -ENODEV; + } + dev_info(dev, "detected ov%04x sensor\n", id); + return 0; +} + +static int os05l10_configure_regulators(struct os05l10 *os05l10) +{ + unsigned int i; + + for (i = 0; i < OS05L10_NUM_SUPPLIES; i++) + os05l10->supplies[i].supply = os05l10_supply_names[i]; + + return devm_regulator_bulk_get(&os05l10->client->dev, + OS05L10_NUM_SUPPLIES, + os05l10->supplies); +} + +static int os05l10_parse_of(struct os05l10 *os05l10) +{ + struct device *dev = &os05l10->client->dev; + struct device_node *endpoint; + struct fwnode_handle *fwnode; + int rval; + unsigned int fps; + + endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); + if (!endpoint) { + dev_err(dev, "Failed to get endpoint\n"); + return -EINVAL; + } + fwnode = of_fwnode_handle(endpoint); + rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0); + if (rval <= 0) { + dev_warn(dev, " Get mipi lane num failed!\n"); + return -1; + } + + os05l10->lane_num = rval; + if (2 == os05l10->lane_num) { + os05l10->cur_mode = &supported_modes_2lane[0]; + supported_modes = supported_modes_2lane; + os05l10->cfg_num = ARRAY_SIZE(supported_modes_2lane); + /*pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ + fps = DIV_ROUND_CLOSEST(os05l10->cur_mode->max_fps.denominator, + os05l10->cur_mode->max_fps.numerator); + os05l10->pixel_rate = os05l10->cur_mode->vts_def * + os05l10->cur_mode->hts_def * fps; + dev_info(dev, "lane_num(%d) pixel_rate(%u)\n", + os05l10->lane_num, os05l10->pixel_rate); + } else { + dev_err(dev, "unsupported lane_num(%d)\n", os05l10->lane_num); + return -1; + } + + return 0; +} + +static int os05l10_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device_node *node = dev->of_node; + struct os05l10 *os05l10; + struct v4l2_subdev *sd; + char facing[2]; + int ret; + struct device_node *eeprom_ctrl_node; + struct i2c_client *eeprom_ctrl_client; + struct v4l2_subdev *eeprom_ctrl; + struct otp_info *otp_ptr; + + dev_info(dev, "driver version: %02x.%02x.%02x", + DRIVER_VERSION >> 16, + (DRIVER_VERSION & 0xff00) >> 8, + DRIVER_VERSION & 0x00ff); + + os05l10 = devm_kzalloc(dev, sizeof(*os05l10), GFP_KERNEL); + if (!os05l10) + return -ENOMEM; + + ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, + &os05l10->module_index); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, + &os05l10->module_facing); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME, + &os05l10->module_name); + ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME, + &os05l10->len_name); + if (ret) { + dev_err(dev, "could not get module information!\n"); + return -EINVAL; + } + os05l10->client = client; + + os05l10->xvclk = devm_clk_get(dev, "xvclk"); + if (IS_ERR(os05l10->xvclk)) { + dev_err(dev, "Failed to get xvclk\n"); + return -EINVAL; + } + + os05l10->power_gpio = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW); + if (IS_ERR(os05l10->power_gpio)) + dev_warn(dev, "Failed to get power-gpios, maybe no use\n"); + os05l10->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(os05l10->reset_gpio)) + dev_warn(dev, "Failed to get reset-gpios\n"); + + os05l10->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); + if (IS_ERR(os05l10->pwdn_gpio)) + dev_warn(dev, "Failed to get pwdn-gpios\n"); + + ret = os05l10_configure_regulators(os05l10); + if (ret) { + dev_err(dev, "Failed to get power regulators\n"); + return ret; + } + + ret = os05l10_parse_of(os05l10); + if (ret != 0) + return -EINVAL; + + os05l10->pinctrl = devm_pinctrl_get(dev); + if (!IS_ERR(os05l10->pinctrl)) { + os05l10->pins_default = + pinctrl_lookup_state(os05l10->pinctrl, + OF_CAMERA_PINCTRL_STATE_DEFAULT); + if (IS_ERR(os05l10->pins_default)) + dev_err(dev, "could not get default pinstate\n"); + + os05l10->pins_sleep = + pinctrl_lookup_state(os05l10->pinctrl, + OF_CAMERA_PINCTRL_STATE_SLEEP); + if (IS_ERR(os05l10->pins_sleep)) + dev_err(dev, "could not get sleep pinstate\n"); + } + + mutex_init(&os05l10->mutex); + + sd = &os05l10->subdev; + v4l2_i2c_subdev_init(sd, client, &os05l10_subdev_ops); + ret = os05l10_initialize_controls(os05l10); + if (ret) + goto err_destroy_mutex; + + ret = __os05l10_power_on(os05l10); + if (ret) + goto err_free_handler; + + ret = os05l10_check_sensor_id(os05l10, client); + if (ret) + goto err_power_off; + + eeprom_ctrl_node = of_parse_phandle(node, "eeprom-ctrl", 0); + if (eeprom_ctrl_node) { + eeprom_ctrl_client = + of_find_i2c_device_by_node(eeprom_ctrl_node); + of_node_put(eeprom_ctrl_node); + if (IS_ERR_OR_NULL(eeprom_ctrl_client)) { + dev_err(dev, "can not get node\n"); + goto continue_probe; + } + eeprom_ctrl = i2c_get_clientdata(eeprom_ctrl_client); + if (IS_ERR_OR_NULL(eeprom_ctrl)) { + dev_err(dev, "can not get eeprom i2c client\n"); + } else { + otp_ptr = devm_kzalloc(dev, sizeof(*otp_ptr), GFP_KERNEL); + if (!otp_ptr) + return -ENOMEM; + ret = v4l2_subdev_call(eeprom_ctrl, + core, ioctl, 0, otp_ptr); + if (!ret) { + os05l10->otp = otp_ptr; + } else { + os05l10->otp = NULL; + devm_kfree(dev, otp_ptr); + dev_warn(dev, "can not get otp info, skip!\n"); + } + } + } +continue_probe: + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + sd->internal_ops = &os05l10_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_HAS_EVENTS; +#endif +#if defined(CONFIG_MEDIA_CONTROLLER) + os05l10->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&sd->entity, 1, &os05l10->pad); + if (ret < 0) + goto err_power_off; +#endif + + memset(facing, 0, sizeof(facing)); + if (strcmp(os05l10->module_facing, "back") == 0) + facing[0] = 'b'; + else + facing[0] = 'f'; + + snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", + os05l10->module_index, facing, + OS05L10_NAME, dev_name(sd->dev)); + ret = v4l2_async_register_subdev_sensor(sd); + if (ret) { + dev_err(dev, "v4l2 async register subdev failed\n"); + goto err_clean_entity; + } + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + return 0; + +err_clean_entity: +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif +err_power_off: + __os05l10_power_off(os05l10); +err_free_handler: + v4l2_ctrl_handler_free(&os05l10->ctrl_handler); +err_destroy_mutex: + mutex_destroy(&os05l10->mutex); + + return ret; +} + +static void os05l10_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct os05l10 *os05l10 = to_os05l10(sd); + + v4l2_async_unregister_subdev(sd); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif + v4l2_ctrl_handler_free(&os05l10->ctrl_handler); + mutex_destroy(&os05l10->mutex); + + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + __os05l10_power_off(os05l10); + pm_runtime_set_suspended(&client->dev); +} + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id os05l10_of_match[] = { + { .compatible = "ovti,os05l10" }, + {}, +}; +MODULE_DEVICE_TABLE(of, os05l10_of_match); +#endif + +static const struct i2c_device_id os05l10_match_id[] = { + { "ovti,os05l10", 0}, + { }, +}; + +static struct i2c_driver os05l10_i2c_driver = { + .driver = { + .name = OS05L10_NAME, + .pm = &os05l10_pm_ops, + .of_match_table = of_match_ptr(os05l10_of_match), + }, + .probe = &os05l10_probe, + .remove = &os05l10_remove, + .id_table = os05l10_match_id, +}; + +static int __init sensor_mod_init(void) +{ + return i2c_add_driver(&os05l10_i2c_driver); +} + +static void __exit sensor_mod_exit(void) +{ + i2c_del_driver(&os05l10_i2c_driver); +} + +device_initcall_sync(sensor_mod_init); +module_exit(sensor_mod_exit); + +MODULE_DESCRIPTION("OmniVision os05l10 sensor driver"); +MODULE_LICENSE("GPL"); From 48cc83ec5e5e5ad198ce70f787312e11eeac097b Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Thu, 21 Nov 2024 09:05:53 +0800 Subject: [PATCH 02/51] clk: rockchip: clk-pvtpll: Add support to adjust pvtpll by volt-sel and otp Change-Id: I3a3c63874454b130a20c96ecb95186c3a9290373 Signed-off-by: Liang Chen --- drivers/clk/rockchip/clk-pvtpll.c | 208 ++++++++++++++++++++++++++++-- drivers/clk/rockchip/clk.h | 9 ++ 2 files changed, 205 insertions(+), 12 deletions(-) diff --git a/drivers/clk/rockchip/clk-pvtpll.c b/drivers/clk/rockchip/clk-pvtpll.c index 7cf4889e5aff..0900b6716a61 100644 --- a/drivers/clk/rockchip/clk-pvtpll.c +++ b/drivers/clk/rockchip/clk-pvtpll.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,8 @@ #include #include "clk.h" +#define MHz 1000000 + #define RV1103B_PVTPLL_GCK_CFG 0x20 #define RV1103B_PVTPLL_GCK_LEN 0x24 #define RV1103B_GCK_START BIT(0) @@ -36,6 +39,7 @@ #define RK3506_START BIT(0) #define RK3506_RING_LENGTH_SEL_OFFSET 0 #define RK3506_RING_LENGTH_SEL_MASK 0x7f +#define RK3506_PVTPLL_MAX_LENGTH 0x7f struct rockchip_clock_pvtpll; @@ -44,17 +48,25 @@ struct pvtpll_table { u32 length; u32 length_frac; u32 ring_sel; + u32 volt_sel_thr; }; struct rockchip_clock_pvtpll_info { unsigned int table_size; struct pvtpll_table *table; + unsigned int jm_table_size; + struct pvtpll_table *jm_table; int (*config)(struct rockchip_clock_pvtpll *pvtpll, struct pvtpll_table *table); + int (*pvtpll_volt_sel_adjust)(struct rockchip_clock_pvtpll *pvtpll, + u32 clock_id, + u32 volt_sel); }; struct rockchip_clock_pvtpll { - const struct rockchip_clock_pvtpll_info *info; + struct device *dev; + struct list_head list_head; + struct rockchip_clock_pvtpll_info *info; struct regmap *regmap; struct clk_hw hw; struct clk *main_clk; @@ -63,8 +75,19 @@ struct rockchip_clock_pvtpll { struct clk *pvtpll_out; struct notifier_block pvtpll_nb; unsigned long cur_rate; + u32 pvtpll_clk_id; }; +static LIST_HEAD(rockchip_clock_pvtpll_list); +static DEFINE_MUTEX(pvtpll_list_mutex); + +struct otp_opp_info { + u16 min_freq; + u16 max_freq; + u8 volt; + u8 length; +} __packed; + #define ROCKCHIP_PVTPLL(_rate, _sel, _len) \ { \ .rate = _rate##U, \ @@ -72,6 +95,14 @@ struct rockchip_clock_pvtpll { .length = _len, \ } +#define ROCKCHIP_PVTPLL_VOLT_SEL(_rate, _sel, _len, _volt_sel_thr) \ +{ \ + .rate = _rate##U, \ + .ring_sel = _sel, \ + .length = _len, \ + .volt_sel_thr = _volt_sel_thr, \ +} + static struct pvtpll_table rv1103b_core_pvtpll_table[] = { /* rate_hz, ring_sel, length */ ROCKCHIP_PVTPLL(1608000000, 1, 6), @@ -92,13 +123,25 @@ static struct pvtpll_table rv1103b_npu_pvtpll_table[] = { }; static struct pvtpll_table rk3506_core_pvtpll_table[] = { - /* rate_hz, ring_sel, length */ - ROCKCHIP_PVTPLL(1608000000, 0, 6), - ROCKCHIP_PVTPLL(1512000000, 0, 6), - ROCKCHIP_PVTPLL(1416000000, 0, 6), - ROCKCHIP_PVTPLL(1296000000, 0, 6), - ROCKCHIP_PVTPLL(1200000000, 0, 8), - ROCKCHIP_PVTPLL(1008000000, 0, 15), + /* rate_hz, ring_sel, length, volt_sel_thr */ + ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 0, 6, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1512000000, 0, 6, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1416000000, 0, 6, 5), + ROCKCHIP_PVTPLL_VOLT_SEL(1296000000, 0, 6, 3), + ROCKCHIP_PVTPLL_VOLT_SEL(1200000000, 0, 6, 2), + ROCKCHIP_PVTPLL_VOLT_SEL(1008000000, 0, 10, 4), + ROCKCHIP_PVTPLL_VOLT_SEL(800000000, 0, 18, 4), +}; + +static struct pvtpll_table rk3506j_core_pvtpll_table[] = { + /* rate_hz, ring_sel, length, volt_sel_thr */ + ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 0, 6, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1512000000, 0, 7, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1416000000, 0, 7, 5), + ROCKCHIP_PVTPLL_VOLT_SEL(1296000000, 0, 7, 3), + ROCKCHIP_PVTPLL_VOLT_SEL(1200000000, 0, 7, 2), + ROCKCHIP_PVTPLL_VOLT_SEL(1008000000, 0, 11, 2), + ROCKCHIP_PVTPLL_VOLT_SEL(800000000, 0, 19, 2), }; static struct pvtpll_table @@ -259,6 +302,126 @@ static int clock_pvtpll_regitstor(struct device *dev, pvtpll->pvtpll_out); } +static int rk3506_pvtpll_volt_sel_adjust(struct rockchip_clock_pvtpll *pvtpll, + u32 clock_id, + u32 volt_sel) +{ + struct pvtpll_table *table = pvtpll->info->table; + unsigned int size = pvtpll->info->table_size; + uint32_t delta_len = 0; + int i; + + for (i = 0; i < size; i++) { + if (!table[i].volt_sel_thr) + continue; + if (volt_sel >= table[i].volt_sel_thr) { + delta_len = volt_sel - table[i].volt_sel_thr + 1; + table[i].length += delta_len; + if (table[i].length > RK3506_PVTPLL_MAX_LENGTH) + table[i].length = RK3506_PVTPLL_MAX_LENGTH; + } + } + + return 0; +} + +int rockchip_pvtpll_volt_sel_adjust(u32 clock_id, u32 volt_sel) +{ + struct rockchip_clock_pvtpll *pvtpll; + int ret = -ENODEV; + + mutex_lock(&pvtpll_list_mutex); + list_for_each_entry(pvtpll, &rockchip_clock_pvtpll_list, list_head) { + if ((pvtpll->pvtpll_clk_id == clock_id) && pvtpll->info->pvtpll_volt_sel_adjust) { + ret = pvtpll->info->pvtpll_volt_sel_adjust(pvtpll, clock_id, volt_sel); + break; + } + } + mutex_unlock(&pvtpll_list_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(rockchip_pvtpll_volt_sel_adjust); + +static int rockchip_pvtpll_get_otp_info(struct device *dev, + struct otp_opp_info *opp_info) +{ + struct nvmem_cell *cell; + void *buf; + size_t len = 0; + + cell = nvmem_cell_get(dev, "opp-info"); + if (IS_ERR(cell)) + return PTR_ERR(cell); + + buf = nvmem_cell_read(cell, &len); + if (IS_ERR(buf)) { + nvmem_cell_put(cell); + return PTR_ERR(buf); + } + if (len != sizeof(*opp_info)) { + kfree(buf); + nvmem_cell_put(cell); + return -EINVAL; + } + + memcpy(opp_info, buf, sizeof(*opp_info)); + kfree(buf); + nvmem_cell_put(cell); + + return 0; +} + +static void rockchip_switch_pvtpll_table(struct device *dev, + struct rockchip_clock_pvtpll *pvtpll) +{ + u8 spec = 0; + + if (!pvtpll->info->jm_table) + return; + + if (!nvmem_cell_read_u8(dev, "specification_serial_number", &spec)) { + /* M = 0xd, J = 0xa */ + if ((spec == 0xd) || (spec == 0xa)) { + pvtpll->info->table = pvtpll->info->jm_table; + pvtpll->info->table_size = pvtpll->info->jm_table_size; + } + } +} + +static void rockchip_adjust_pvtpll_by_otp(struct device *dev, + struct rockchip_clock_pvtpll *pvtpll) +{ + struct otp_opp_info opp_info = { 0 }; + struct pvtpll_table *table = pvtpll->info->table; + unsigned int size = pvtpll->info->table_size; + u32 min_freq, max_freq; + int i; + + if (rockchip_pvtpll_get_otp_info(dev, &opp_info)) + return; + + if (!opp_info.length) + return; + + dev_info(dev, "adjust opp-table by otp: min=%uM, max=%uM, length=%u\n", + opp_info.min_freq, opp_info.max_freq, opp_info.length); + + min_freq = opp_info.min_freq * MHz; + max_freq = opp_info.max_freq * MHz; + + for (i = 0; i < size; i++) { + if (table[i].rate < min_freq) + continue; + if (table[i].rate > max_freq) + continue; + + table[i].length += opp_info.length; + if (table[i].length > RK3506_PVTPLL_MAX_LENGTH) + table[i].length = RK3506_PVTPLL_MAX_LENGTH; + } +} + static const struct rockchip_clock_pvtpll_info rv1103b_core_pvtpll_data = { .config = rv1103b_pvtpll_configs, .table_size = ARRAY_SIZE(rv1103b_core_pvtpll_table), @@ -275,6 +438,9 @@ static const struct rockchip_clock_pvtpll_info rk3506_core_pvtpll_data = { .config = rk3506_pvtpll_configs, .table_size = ARRAY_SIZE(rk3506_core_pvtpll_table), .table = rk3506_core_pvtpll_table, + .jm_table_size = ARRAY_SIZE(rk3506j_core_pvtpll_table), + .jm_table = rk3506j_core_pvtpll_table, + .pvtpll_volt_sel_adjust = rk3506_pvtpll_volt_sel_adjust, }; static const struct of_device_id rockchip_clock_pvtpll_match[] = { @@ -299,13 +465,14 @@ static int rockchip_clock_pvtpll_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = pdev->dev.of_node; struct rockchip_clock_pvtpll *pvtpll; + struct of_phandle_args clkspec = { 0 }; int error = 0; pvtpll = devm_kzalloc(dev, sizeof(*pvtpll), GFP_KERNEL); if (!pvtpll) return -ENOMEM; - pvtpll->info = (const struct rockchip_clock_pvtpll_info *)device_get_match_data(&pdev->dev); + pvtpll->info = (struct rockchip_clock_pvtpll_info *)device_get_match_data(&pdev->dev); if (!pvtpll->info) return -EINVAL; @@ -313,15 +480,32 @@ static int rockchip_clock_pvtpll_probe(struct platform_device *pdev) if (IS_ERR(pvtpll->regmap)) return PTR_ERR(pvtpll->regmap); + pvtpll->pvtpll_clk_id = UINT_MAX; + + error = of_parse_phandle_with_args(np, "clocks", "#clock-cells", + 0, &clkspec); + if (!error) { + pvtpll->pvtpll_clk_id = clkspec.args[0]; + of_node_put(clkspec.np); + } + + rockchip_switch_pvtpll_table(dev, pvtpll); + + rockchip_adjust_pvtpll_by_otp(dev, pvtpll); + platform_set_drvdata(pdev, pvtpll); error = clock_pvtpll_regitstor(&pdev->dev, pvtpll); if (error) { - dev_err(&pdev->dev, "failed to register clock: %d\n", - error); + dev_err(&pdev->dev, "failed to register clock: %d\n", error); + return error; } - return error; + mutex_lock(&pvtpll_list_mutex); + list_add(&pvtpll->list_head, &rockchip_clock_pvtpll_list); + mutex_unlock(&pvtpll_list_mutex); + + return 0; } static int rockchip_clock_pvtpll_remove(struct platform_device *pdev) diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 0a25a11c0588..7441b7e604b8 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -774,6 +774,15 @@ struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, } #endif +#if IS_REACHABLE(CONFIG_ROCKCHIP_CLK_PVTPLL) +int rockchip_pvtpll_volt_sel_adjust(u32 clock_id, u32 volt_sel); +#else +static inline int rockchip_pvtpll_volt_sel_adjust(u32 clock_id, u32 volt_sel) +{ + return -ENODEV; +} +#endif + #define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0) struct clk *rockchip_clk_register_inverter(const char *name, From 3f9ac9b16189e8e5d7a58c87e153200fbfd33d41 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Wed, 27 Nov 2024 10:31:12 +0800 Subject: [PATCH 03/51] soc: rockchip: opp_select: adjust pvtpll by volt-sel in clk-pvtpll driver Change-Id: I9f2142dcea31acf688555646db3dbe4576104b54 Signed-off-by: Liang Chen --- drivers/soc/rockchip/rockchip_opp_select.c | 7 ++++++- include/soc/rockchip/rockchip_opp_select.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/soc/rockchip/rockchip_opp_select.c b/drivers/soc/rockchip/rockchip_opp_select.c index 549c8b6c5b4f..e7f0644600b4 100644 --- a/drivers/soc/rockchip/rockchip_opp_select.c +++ b/drivers/soc/rockchip/rockchip_opp_select.c @@ -1390,7 +1390,7 @@ static void rockchip_init_pvtpll_table(struct device *dev, res = sip_smc_get_pvtpll_info(PVTPLL_GET_INFO, info->pvtpll_clk_id); if (res.a0) { - info->pvtpll_clk_id = UINT_MAX; + info->pvtpll_smc = false; goto out; } if (!res.a1) @@ -1698,6 +1698,7 @@ int rockchip_init_opp_info(struct device *dev, struct rockchip_opp_info *info, info->process = -EINVAL; info->volt_sel = -EINVAL; info->pvtpll_clk_id = UINT_MAX; + info->pvtpll_smc = true; info->is_runtime_active = true; mutex_init(&info->dvfs_mutex); @@ -2070,6 +2071,10 @@ static int rockchip_pvtpll_set_volt_sel(struct device *dev, if (info->pvtpll_clk_id == UINT_MAX) return 0; + if (!info->pvtpll_smc) + return rockchip_pvtpll_volt_sel_adjust(info->pvtpll_clk_id, + info->volt_sel); + res = sip_smc_pvtpll_config(PVTPLL_VOLT_SEL, info->pvtpll_clk_id, (u32)info->volt_sel, 0, 0, 0, 0); if (res.a0) diff --git a/include/soc/rockchip/rockchip_opp_select.h b/include/soc/rockchip/rockchip_opp_select.h index f448b3814508..e11c4cccd4bb 100644 --- a/include/soc/rockchip/rockchip_opp_select.h +++ b/include/soc/rockchip/rockchip_opp_select.h @@ -97,6 +97,7 @@ struct pvtpll_opp_table { * @init_freq: Set the initial frequency when init opp table. * @is_rate_volt_checked: Marks if device has checked initial rate and voltage. * @pvtpll_clk_id: Device's clock id. + * @pvtpll_smc: Marks if smc call of pvtpll is available. * @pvtpll_low_temp: Marks if device has low temperature pvtpll config. */ struct rockchip_opp_info { @@ -138,6 +139,7 @@ struct rockchip_opp_info { bool is_rate_volt_checked; u32 pvtpll_clk_id; + bool pvtpll_smc; bool pvtpll_low_temp; }; From 98e1dfc90c0f4814611c2a7f9839d5f6b5c3a2fa Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Fri, 22 Nov 2024 11:03:18 +0800 Subject: [PATCH 04/51] ARM: dts: rockchip: rk3502: update opp-table for cpu Change-Id: Ic8668f5dcf6381729a2377c192e9c87a09042ee2 Signed-off-by: Liang Chen --- arch/arm/boot/dts/rk3502.dtsi | 192 ++++++++++++++++++++++++++-------- 1 file changed, 148 insertions(+), 44 deletions(-) diff --git a/arch/arm/boot/dts/rk3502.dtsi b/arch/arm/boot/dts/rk3502.dtsi index 1ad8c6d72918..7670de472f32 100644 --- a/arch/arm/boot/dts/rk3502.dtsi +++ b/arch/arm/boot/dts/rk3502.dtsi @@ -142,10 +142,13 @@ pvtpll_core: pvtpll-core@ff840000 { compatible = "rockchip,rk3506-core-pvtpll", "syscon"; reg = <0xff840000 0x100>; + clocks = <&cru ARMCLK>; #clock-cells = <0>; clock-output-names = "clk_core_pvtpll"; assigned-clocks = <&pvtpll_core>; assigned-clock-rates = <1200000000>; + nvmem-cells = <&cpu_opp_info>, <&specification_serial_number>; + nvmem-cell-names = "opp-info", "specification_serial_number"; }; sai0_fs: sai0-fs { @@ -213,23 +216,28 @@ compatible = "operating-points-v2"; opp-shared; - nvmem-cells = <&cpu_leakage>; - nvmem-cell-names = "leakage"; + mbist-vmin = <850000 900000 975000>; + nvmem-cells = <&cpu_leakage>, <&cpu_opp_info>, <&cpu_mbist_vmin>, <&cpu_pvtpll>, + <&specification_serial_number>; + nvmem-cell-names = "leakage", "opp-info", "mbist-vmin", "pvtm", + "specification_serial_number"; rockchip,temp-freq-table = < 85000 1008000 100000 600000 >; + rockchip,supported-hw; rockchip,pvtm-voltage-sel = < - 0 1584 0 - 1585 1619 1 - 1620 1654 2 - 1655 1689 3 - 1690 1724 4 - 1725 1759 5 - 1760 1794 6 - 1795 9999 7 + 0 1520 0 + 1521 1584 1 + 1585 1648 2 + 1649 1712 3 + 1713 1776 4 + 1777 1840 5 + 1841 1904 6 + 1905 1968 7 + 1969 9999 8 >; rockchip,pvtm-pvtpll; rockchip,pvtm-offset = <0x18>; @@ -242,70 +250,152 @@ rockchip,grf = <&pvtpll_core>; rockchip,temp-hysteresis = <5000>; rockchip,low-temp = <10000>; - rockchip,low-temp-min-volt = <900000>; + rockchip,low-temp-min-volt = <950000>; opp-600000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <600000000>; - opp-microvolt = <850000 850000 1000000>; + opp-microvolt = <850000 850000 1100000>; + opp-microvolt-L0 = <900000 900000 1100000>; + opp-microvolt-L1 = <900000 900000 1100000>; + opp-microvolt-L2 = <875000 875000 1100000>; clock-latency-ns = <40000>; opp-suspend; }; opp-800000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <800000000>; - opp-microvolt = <850000 850000 1000000>; + opp-microvolt = <850000 850000 1100000>; + opp-microvolt-L0 = <900000 900000 1100000>; + opp-microvolt-L1 = <900000 900000 1100000>; + opp-microvolt-L2 = <875000 875000 1100000>; clock-latency-ns = <40000>; }; opp-1008000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1008000000>; - opp-microvolt = <850000 850000 1000000>; - opp-microvolt-L0 = <875000 875000 1000000>; + opp-microvolt = <850000 850000 1100000>; + opp-microvolt-L0 = <900000 900000 1100000>; + opp-microvolt-L1 = <900000 900000 1100000>; + opp-microvolt-L2 = <875000 875000 1100000>; clock-latency-ns = <40000>; }; opp-1200000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <850000 850000 1000000>; - opp-microvolt-L0 = <875000 875000 1000000>; + opp-microvolt = <900000 900000 1100000>; clock-latency-ns = <40000>; }; opp-1296000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1296000000>; - opp-microvolt = <900000 900000 1000000>; - opp-microvolt-L0 = <900000 900000 1000000>; - opp-microvolt-L1 = <887500 887500 1000000>; - opp-microvolt-L2 = <875000 875000 1000000>; - opp-microvolt-L3 = <862500 862500 1000000>; - opp-microvolt-L4 = <850000 850000 1000000>; - opp-microvolt-L5 = <850000 850000 1000000>; - opp-microvolt-L6 = <850000 850000 1000000>; - opp-microvolt-L7 = <850000 850000 1000000>; + opp-microvolt = <900000 900000 1100000>; + opp-microvolt-L0 = <950000 950000 1100000>; + opp-microvolt-L1 = <925000 925000 1100000>; clock-latency-ns = <40000>; }; opp-1416000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1416000000>; - opp-microvolt = <937500 937500 1000000>; - opp-microvolt-L0 = <937500 937500 1000000>; - opp-microvolt-L1 = <925000 925000 1000000>; - opp-microvolt-L2 = <912500 912500 1000000>; - opp-microvolt-L3 = <900000 900000 1000000>; - opp-microvolt-L4 = <887500 887500 1000000>; - opp-microvolt-L5 = <875000 875000 1000000>; - opp-microvolt-L6 = <862500 862500 1000000>; - opp-microvolt-L7 = <850000 850000 1000000>; + opp-microvolt = <900000 900000 1100000>; + opp-microvolt-L0 = <1000000 1000000 1100000>; + opp-microvolt-L1 = <975000 975000 1100000>; + opp-microvolt-L2 = <950000 950000 1100000>; + opp-microvolt-L3 = <925000 925000 1100000>; clock-latency-ns = <40000>; }; opp-1512000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <975000 975000 1000000>; - opp-microvolt-L0 = <975000 975000 1000000>; - opp-microvolt-L1 = <962500 962500 1000000>; - opp-microvolt-L2 = <950000 950000 1000000>; - opp-microvolt-L3 = <937500 937500 1000000>; - opp-microvolt-L4 = <925000 925000 1000000>; - opp-microvolt-L5 = <912500 912000 1000000>; - opp-microvolt-L6 = <900000 900000 1000000>; - opp-microvolt-L7 = <887500 887500 1000000>; + opp-microvolt = <900000 900000 1100000>; + opp-microvolt-L0 = <1050000 1050000 1100000>; + opp-microvolt-L1 = <1025000 1025000 1100000>; + opp-microvolt-L2 = <1000000 1000000 1100000>; + opp-microvolt-L3 = <975000 975000 1100000>; + opp-microvolt-L4 = <950000 950000 1100000>; + opp-microvolt-L5 = <925000 925000 1100000>; clock-latency-ns = <40000>; }; + opp-1608000000 { + opp-supported-hw = <0xf9 0xffff>; + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <950000 950000 1100000>; + opp-microvolt-L0 = <1100000 1100000 1100000>; + opp-microvolt-L1 = <1075000 1075000 1100000>; + opp-microvolt-L2 = <1050000 1050000 1100000>; + opp-microvolt-L3 = <1025000 1025000 1100000>; + opp-microvolt-L4 = <1000000 1000000 1100000>; + opp-microvolt-L5 = <975000 975000 1100000>; + clock-latency-ns = <40000>; + }; + + /* RK3506J cpu OPPs */ + opp-j-600000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <900000 900000 1050000>; + clock-latency-ns = <40000>; + opp-suspend; + }; + opp-j-800000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <900000 900000 1050000>; + clock-latency-ns = <40000>; + }; + opp-j-1008000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1008000000>; + opp-microvolt = <900000 900000 1050000>; + clock-latency-ns = <40000>; + }; + opp-j-1200000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <900000 900000 1050000>; + clock-latency-ns = <40000>; + }; + /* + * The Max frequency is 1200MHz in default normal mode. + * The Max frequency is 1512MHz in overdrive mode, + * but under the overdrive mode for a long time, + * the chipset may shorten the lifetime, especially in high + * temperature condition. Disable overdrive opps by default + * and you can enable them in dts file. + */ + cpu_opp_j_od_1296000000: opp-j-od-1296000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1296000000>; + opp-microvolt = <925000 925000 1050000>; + opp-microvolt-L0 = <950000 950000 1050000>; + opp-microvolt-L1 = <950000 950000 1050000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; + cpu_opp_j_od_1416000000: opp-j-od-1416000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1416000000>; + opp-microvolt = <925000 925000 1050000>; + opp-microvolt-L0 = <1000000 1000000 1050000>; + opp-microvolt-L1 = <1000000 1000000 1050000>; + opp-microvolt-L2 = <975000 975000 1050000>; + opp-microvolt-L3 = <950000 950000 1050000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; + cpu_opp_j_od_1512000000: opp-j-od-1512000000 { + opp-supported-hw = <0xf9 0xffff>; + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <925000 925000 1050000>; + opp-microvolt-L0 = <1050000 1050000 1050000>; + opp-microvolt-L1 = <1050000 1050000 1050000>; + opp-microvolt-L2 = <1025000 1025000 1050000>; + opp-microvolt-L3 = <1000000 1000000 1050000>; + opp-microvolt-L4 = <975000 975000 1050000>; + opp-microvolt-L5 = <950000 950000 1050000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; }; arm_pmu: arm-pmu { @@ -1085,6 +1175,10 @@ reg = <0x05 0x1>; bits = <3 3>; }; + specification_serial_number: specification-serial-number@8 { + reg = <0x08 0x1>; + bits = <0 5>; + }; otp_id: id@a { reg = <0x0a 0x10>; }; @@ -1101,6 +1195,16 @@ reg = <0x21 0x1>; bits = <0 2>; }; + cpu_opp_info: cpu-opp-info@24 { + reg = <0x24 0x6>; + }; + cpu_pvtpll: cpu-pvtpll@30 { + reg = <0x30 0x2>; + }; + cpu_mbist_vmin: mbist-vmin@33 { + reg = <0x33 0x1>; + bits = <0 4>; + }; }; audio_codec: audio-codec@ff4f8000 { From 8836ecc22a28c8e7b5d05220cf3a697fb437f6c8 Mon Sep 17 00:00:00 2001 From: Mark Huang Date: Tue, 10 Dec 2024 11:37:00 +0800 Subject: [PATCH 05/51] ARM: dts: rockchip: add RK3528 demo4 board devicetree Signed-off-by: Mark Huang Change-Id: I6ce3b7efc221550572d18ff39a3fdc165849c6e1 --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/rk3528-demo4-ddr4-v10.dts | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 arch/arm/boot/dts/rk3528-demo4-ddr4-v10.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 4766765424fd..ae67bb3e23f9 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1238,6 +1238,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3506g-iotest-v10.dtb \ rk3506g-iotest-v10-pdm.dtb \ rk3506g-test1-v10-audio.dtb \ + rk3528-demo4-ddr4-v10.dtb \ rk3528-evb1-ddr4-v10.dtb \ rk3528-evb2-ddr3-v10.dtb \ rk3528-evb3-lp4x-v10.dtb \ diff --git a/arch/arm/boot/dts/rk3528-demo4-ddr4-v10.dts b/arch/arm/boot/dts/rk3528-demo4-ddr4-v10.dts new file mode 100644 index 000000000000..78674a2c197e --- /dev/null +++ b/arch/arm/boot/dts/rk3528-demo4-ddr4-v10.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ + +#include "arm64/rockchip/rk3528-demo4-ddr4-v10.dts" From 5e8b5902eacf5b4581ba9b40ae435fe1d1544063 Mon Sep 17 00:00:00 2001 From: Mark Huang Date: Tue, 17 Dec 2024 10:43:26 +0800 Subject: [PATCH 06/51] arm64: dts: rockchip: rk3528-evb1-ddr4-v10: add power on delay to fix wifi open fail Signed-off-by: Mark Huang Change-Id: I980007a467b911b5b6992c25ce3289eab8e3552e --- arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi index 822d6145d3e6..c3c340968ddd 100644 --- a/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi @@ -17,7 +17,9 @@ compatible = "mmc-pwrseq-simple"; pinctrl-names = "default"; pinctrl-0 = <&wifi_enable_h &clkm1_32k_out>; + post-power-on-delay-ms = <200>; reset-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + status = "okay"; }; wireless_bluetooth: wireless-bluetooth { From b358a51aeffb8a0b055133d0053f5b2a5eb96e50 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Mon, 16 Dec 2024 11:32:30 +0800 Subject: [PATCH 07/51] drm/rockchip: vop2: fix the sys port ctrl reg config of rk3576 Change-Id: I277605413e4f6e3abdcfe07942a92a717e31a9bf Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 1ac78f575389..7fe266b500a0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -4658,7 +4658,7 @@ static const struct vop2_ctrl rk3576_vop_ctrl = { .version = VOP_REG(RK3568_VERSION_INFO, 0xffff, 16), .lut_dma_en = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1, 0), .lut_use_axi1 = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1, 9), - .dsp_vs_t_sel = VOP_REG(RK3576_SYS_PORT_CTRL_IMD, 0x1, 4), + .dsp_vs_t_sel = VOP_REG_MASK(RK3576_SYS_PORT_CTRL_IMD, 0x1, 4), .rkmmu_v2_en = VOP_REG_MASK(RK3576_SYS_MMU_CTRL_IMD, 0x1, 0), .rkmmu_v2_sel_axi = VOP_REG_MASK(RK3576_SYS_MMU_CTRL_IMD, 0x1, 1), From 41fe643f8cdc438aaccf7b0005c23c2b3e6d02e8 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Sat, 12 Mar 2022 11:55:15 +0800 Subject: [PATCH 08/51] drm/rockchp: dw-dp: enable video stream fifo overflow irq Signed-off-by: Zhang Yubing Change-Id: I73e33d60db8886b150c390b387ba360bafbc0b72 --- drivers/gpu/drm/rockchip/dw-dp.c | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index 94fc6a4987d4..a7400bf99953 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -171,6 +171,9 @@ #define DPTX_AUX_DATA3 0x0b14 #define DPTX_GENERAL_INTERRUPT 0x0d00 +#define VIDEO_FIFO_OVERFLOW_STREAM3 BIT(26) +#define VIDEO_FIFO_OVERFLOW_STREAM2 BIT(20) +#define VIDEO_FIFO_OVERFLOW_STREAM1 BIT(14) #define VIDEO_FIFO_OVERFLOW_STREAM0 BIT(6) #define AUDIO_FIFO_OVERFLOW_STREAM0 BIT(5) #define SDP_EVENT_STREAM0 BIT(4) @@ -2900,6 +2903,14 @@ static void dw_dp_init(struct dw_dp *dp) dw_dp_hpd_init(dp); dw_dp_aux_init(dp); + + regmap_update_bits(dp->regmap, DPTX_GENERAL_INTERRUPT_ENABLE, + VIDEO_FIFO_OVERFLOW_STREAM0 | VIDEO_FIFO_OVERFLOW_STREAM1 | + VIDEO_FIFO_OVERFLOW_STREAM2 | VIDEO_FIFO_OVERFLOW_STREAM3, + FIELD_PREP(VIDEO_FIFO_OVERFLOW_STREAM0, 1) | + FIELD_PREP(VIDEO_FIFO_OVERFLOW_STREAM1, 1) | + FIELD_PREP(VIDEO_FIFO_OVERFLOW_STREAM2, 1) | + FIELD_PREP(VIDEO_FIFO_OVERFLOW_STREAM3, 1)); } static void dw_dp_encoder_enable(struct drm_encoder *encoder) @@ -5084,6 +5095,30 @@ static irqreturn_t dw_dp_irq_handler(int irq, void *data) if (value & HDCP_EVENT) dw_dp_handle_hdcp_event(dp); + if (value & VIDEO_FIFO_OVERFLOW_STREAM0) { + dev_err_ratelimited(dp->dev, "video fifo overflow stream0\n"); + regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT, + VIDEO_FIFO_OVERFLOW_STREAM0); + } + + if (value & VIDEO_FIFO_OVERFLOW_STREAM1) { + dev_err_ratelimited(dp->dev, "video fifo overflow stream1\n"); + regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT, + VIDEO_FIFO_OVERFLOW_STREAM1); + } + + if (value & VIDEO_FIFO_OVERFLOW_STREAM2) { + dev_err_ratelimited(dp->dev, "video fifo overflow stream2\n"); + regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT, + VIDEO_FIFO_OVERFLOW_STREAM2); + } + + if (value & VIDEO_FIFO_OVERFLOW_STREAM3) { + dev_err_ratelimited(dp->dev, "video fifo overflow stream3\n"); + regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT, + VIDEO_FIFO_OVERFLOW_STREAM3); + } + return IRQ_HANDLED; } From f8c680bb5e16db013ed6251f3acdc7f0a36cad30 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Tue, 29 Oct 2024 15:44:35 +0100 Subject: [PATCH 09/51] UPSTREAM: HID: core: zero-initialize the report buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the report buffer is used by all kinds of drivers in various ways, let's zero-initialize it during allocation to make sure that it can't be ever used to leak kernel memory via specially-crafted report. CVE-2024-50302 Change-Id: I949eb045a8e7fdc0be118d2899d9d957395067f1 Fixes: 27ce405039bf ("HID: fix data access in implement()") Reported-by: Benoît Sevens Acked-by: Benjamin Tissoires Signed-off-by: Jiri Kosina Signed-off-by: Tao Huang (cherry picked from commit 177f25d1292c7e16e1199b39c85480f7f8815552) --- drivers/hid/hid-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e2e52aa0eeba..b5887658c6af 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1878,7 +1878,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags) u32 len = hid_report_len(report) + 7; - return kmalloc(len, flags); + return kzalloc(len, flags); } EXPORT_SYMBOL_GPL(hid_alloc_report_buf); From a740751efe044157b9a2aac3817ac673bb105240 Mon Sep 17 00:00:00 2001 From: Benoit Sevens Date: Thu, 7 Nov 2024 14:22:02 +0000 Subject: [PATCH 10/51] UPSTREAM: media: uvcvideo: Skip parsing frames of type UVC_VS_UNDEFINED in uvc_parse_format This can lead to out of bounds writes since frames of this type were not taken into account when calculating the size of the frames buffer in uvc_parse_streaming. CVE-2024-53104 Change-Id: I3dd74072f3b41bab05634f24cfaf8f35a6fae43f Fixes: c0efd232929c ("V4L/DVB (8145a): USB Video Class driver") Signed-off-by: Benoit Sevens Cc: stable@vger.kernel.org Acked-by: Greg Kroah-Hartman Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Tao Huang (cherry picked from commit ecf2b43018da9579842c774b7f35dbe11b5c38dd) --- drivers/media/usb/uvc/uvc_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 88eda75089d3..0679b288c10a 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -369,7 +369,7 @@ static int uvc_parse_format(struct uvc_device *dev, * Parse the frame descriptors. Only uncompressed, MJPEG and frame * based formats have frame descriptors. */ - while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && + while (ftype && buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == ftype) { frame = &format->frame[format->nframes]; if (ftype != UVC_VS_FRAME_FRAME_BASED) From 0c1cb186ff9b1fadf6bf4691af6113f6013604d2 Mon Sep 17 00:00:00 2001 From: Cai Wenzhong Date: Tue, 17 Dec 2024 11:26:39 +0800 Subject: [PATCH 11/51] arm64: dts: rockchip: rk3576-vehicle-evb-v20: add max96712-dphy3-sc233at.dtsi sc233at: MAX96717F, SC233AT, 1920 * 1200, YUV422 8bit Signed-off-by: Cai Wenzhong Change-Id: Ib29acaf03cf7c2f67aa21c08a46f4eba47e12111 --- ...-evb-v20-maxim-max96712-dphy3-sc233at.dtsi | 713 ++++++++++++++++++ 1 file changed, 713 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi new file mode 100644 index 000000000000..07c74718195b --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi @@ -0,0 +1,713 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dphy3_osc: max96712-dphy3-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dphy3-osc"; + }; + + max96712_dphy3_vcc1v2: max96712-dphy3-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_vcc1v8: max96712-dphy3-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_pwdn_regulator: max96712-dphy3-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_pwdn"; + gpio = <&gpio4 RK_PC0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dphy3_poc_regulator: max96712-dphy3-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_poc"; + gpio = <&gpio4 RK_PC3 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dphy3_vcc12v_buck1>; + }; +}; + +&csi2_dphy1_hw { + status = "okay"; +}; + +&csi2_dphy3 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dphy3_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy3_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy3_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi3_csi2_input>; + }; + }; + }; +}; + +&i2c8 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8m2_xfer>; + + max96712_dphy3: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dphy3_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_errb>, <&max96712_dphy3_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dphy3_vcc1v2>; + vcc1v8-supply = <&max96712_dphy3_vcc1v8>; + pwdn-supply = <&max96712_dphy3_pwdn_regulator>; + lock-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dphy3_out: endpoint { + remote-endpoint = <&mipi_dphy3_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1200>; + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "disabled"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser0: max96717@51 { + compatible = "maxim,ser,max96717f"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam0: sc233at@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser0>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser1: max96717@52 { + compatible = "maxim,ser,max96717f"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam1: sc233at@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser1>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser2: max96717@53 { + compatible = "maxim,ser,max96717f"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam2: sc233at@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser2>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser3: max96717@54 { + compatible = "maxim,ser,max96717f"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam3: sc233at@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser3>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi3_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy3_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi3_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds3 { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi3_in: endpoint { + remote-endpoint = <&mipi3_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dphy3 { + max96712_dphy3_pwdn: max96712-dphy3-pwdn { + rockchip,pins = <4 RK_PC0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dphy3_errb: max96712-dphy3-errb { + rockchip,pins = <4 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dphy3_lock: max96712-dphy3-lock { + rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; From a437e6a0169e7fbc18d3d694511dda4c99c4df5c Mon Sep 17 00:00:00 2001 From: Cai Wenzhong Date: Tue, 17 Dec 2024 11:31:45 +0800 Subject: [PATCH 12/51] arm64: dts: rockchip: rk3576-vehicle-evb-v20: support sc233at for DMS Signed-off-by: Cai Wenzhong Change-Id: Iebe371a9bc6eb6a1303fdbf3c9a77e30b4e112cf --- arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dts b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dts index cf790ab86eb9..144b742871ae 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dts +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dts @@ -11,6 +11,7 @@ #include "rk3576-vehicle-evb-v20-nca9539-io-expander.dtsi" #include "rk3576-vehicle-evb-v20-serdes-mfd-display-maxim.dtsi" #include "rk3576-vehicle-evb-v20-maxim-max96712-dphy0-isx021.dtsi" +#include "rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi" #include "rk3576-android.dtsi" / { From 058b229588b79b95bb315a03ef3d875b9d8b42cb Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Tue, 17 Dec 2024 22:38:58 +0800 Subject: [PATCH 13/51] phy: rockchip-snps-pcie3: Configure registers only when defining phy mode Change-Id: I75ef3313d59708f9238dbb7cac3a7f210fb97c9b Signed-off-by: Jon Lin --- drivers/phy/rockchip/phy-rockchip-snps-pcie3.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c index a10e23b68115..5841a41a6703 100644 --- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c @@ -276,17 +276,15 @@ static int rockchip_p3phy_probe(struct platform_device *pdev) dev_info(dev, "failed to find rockchip,pipe_grf regmap\n"); ret = device_property_read_u32(dev, "rockchip,pcie30-phymode", &val); - if (!ret) + if (!ret) { priv->pcie30_phymode = val; - else + if (priv->pcie30_phymode > 4) + priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION; + regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, + (0x7<<16) | priv->pcie30_phymode); + } else { priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION; - - /* Select correct pcie30_phymode */ - if (priv->pcie30_phymode > 4) - priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION; - - regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, - (0x7<<16) | priv->pcie30_phymode); + } /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */ if (!IS_ERR(priv->pipe_grf)) { From 1f97a95049644d48fb75b3fcdd088dd168461804 Mon Sep 17 00:00:00 2001 From: Cai Wenzhong Date: Tue, 17 Dec 2024 11:26:39 +0800 Subject: [PATCH 14/51] arm64: dts: rockchip: rk3576-vehicle-evb-v20: max96712 d(/c)phy0(/3): add more sensor dtsi dummy: MAX96717, DUMMY, 1920 * 1440, YUV422 8bit isx021: MAX96717F, ISX021, 1920 * 1281, YUV422 8bit Signed-off-by: Cai Wenzhong Change-Id: Ic8b0ff43e376a9697c82092190de46c07bcf8eb8 --- ...e-evb-v20-maxim-max96712-dcphy0-dummy.dtsi | 709 +++++++++++++++++ ...-evb-v20-maxim-max96712-dcphy0-isx021.dtsi | 721 +++++++++++++++++ ...le-evb-v20-maxim-max96712-dphy0-dummy.dtsi | 713 +++++++++++++++++ ...le-evb-v20-maxim-max96712-dphy3-dummy.dtsi | 713 +++++++++++++++++ ...e-evb-v20-maxim-max96712-dphy3-isx021.dtsi | 725 ++++++++++++++++++ 5 files changed, 3581 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-dummy.dtsi create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-isx021.dtsi create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy0-dummy.dtsi create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-dummy.dtsi create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-isx021.dtsi diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-dummy.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-dummy.dtsi new file mode 100644 index 000000000000..7236bdab4d9d --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-dummy.dtsi @@ -0,0 +1,709 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dcphy0_osc: max96712-dcphy0-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dcphy0-osc"; + }; + + max96712_dcphy0_vcc1v2: max96712-dcphy0-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dcphy0_vcc1v8: max96712-dcphy0-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dcphy0_pwdn_regulator: max96712-dcphy0-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_pwdn"; + gpio = <&gpio2 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dcphy0_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dcphy0_poc_regulator: max96712-dcphy0-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_poc"; + gpio = <&i2c7_nca9539_gpio 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dcphy0_vcc12v_buck1>; + }; +}; + +&csi2_dcphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dcphy0_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dcphy0_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&i2c7 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7m1_xfer>; + + max96712_dcphy0: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dcphy0_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dcphy0_errb>, <&max96712_dcphy0_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dcphy0_vcc1v2>; + vcc1v8-supply = <&max96712_dcphy0_vcc1v8>; + pwdn-supply = <&max96712_dcphy0_pwdn_regulator>; + lock-gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dcphy0_out: endpoint { + remote-endpoint = <&mipi_dcphy0_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1440>; + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "disabled"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser0: max96717@51 { + compatible = "maxim,ser,max96717"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam0: dummy@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser0>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser1: max96717@52 { + compatible = "maxim,ser,max96717"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam1: dummy@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser1>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser2: max96717@53 { + compatible = "maxim,ser,max96717"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam2: dummy@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser2>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser3: max96717@54 { + compatible = "maxim,ser,max96717"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam3: dummy@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser3>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi0_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi0_in: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dcphy0 { + max96712_dcphy0_pwdn: max96712-dcphy0-pwdn { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dcphy0_errb: max96712-dcphy0-errb { + rockchip,pins = <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dcphy0_lock: max96712-dcphy0-lock { + rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-isx021.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-isx021.dtsi new file mode 100644 index 000000000000..8efc11645df5 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-isx021.dtsi @@ -0,0 +1,721 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dcphy0_osc: max96712-dcphy0-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dcphy0-osc"; + }; + + max96712_dcphy0_vcc1v2: max96712-dcphy0-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dcphy0_vcc1v8: max96712-dcphy0-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dcphy0_pwdn_regulator: max96712-dcphy0-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_pwdn"; + gpio = <&gpio2 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dcphy0_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dcphy0_poc_regulator: max96712-dcphy0-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_poc"; + gpio = <&i2c7_nca9539_gpio 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dcphy0_vcc12v_buck1>; + }; +}; + +&csi2_dcphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dcphy0_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dcphy0_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&i2c7 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7m1_xfer>; + + max96712_dcphy0: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dcphy0_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dcphy0_errb>, <&max96712_dcphy0_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dcphy0_vcc1v2>; + vcc1v8-supply = <&max96712_dcphy0_vcc1v8>; + pwdn-supply = <&max96712_dcphy0_pwdn_regulator>; + lock-gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dcphy0_out: endpoint { + remote-endpoint = <&mipi_dcphy0_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1281>; + crop-rect = <0 1 1920 1280>; // [ left, top, width, height ] + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "okay"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + 04 A2 00 00 00 // Master link Video 0 for frame sync generation + 04 AA 00 00 00 // Disable Vsync-Fsync overlap window + 04 AB 00 00 00 // Disable Vsync-Fsync overlap window + 04 A8 00 00 00 // FRM_DIFF_ERR_THR_L + 04 A9 00 00 00 // FRM_DIFF_ERR_THR_H + 04 A7 0c 00 00 // FSYNC_PERIOD_H, Set FSYNC period to 25M/30 clock cycles. PCLK = 25MHz. Sync freq = 30Hz + 04 A6 bf 00 00 // FSYNC_PERIOD_M + 04 A5 35 00 00 // FSYNC_PERIOD_L + 04 AF c0 00 00 // FSYNC is GMSL2 type, use osc for fsync + 04 B1 40 00 00 // FSYNC_TX_ID: set 8 to match MFP8 on serializer side + 04 A0 04 00 00 // MFP2, VS not gen internally, GPIO not used to gen fsync, manual mode + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser0: max96717@51 { + compatible = "maxim,ser,max96717f"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam0: isx021@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser0>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser1: max96717@52 { + compatible = "maxim,ser,max96717f"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam1: isx021@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser1>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser2: max96717@53 { + compatible = "maxim,ser,max96717f"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam2: isx021@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser2>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser3: max96717@54 { + compatible = "maxim,ser,max96717f"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam3: isx021@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser3>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi0_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi0_in: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dcphy0 { + max96712_dcphy0_pwdn: max96712-dcphy0-pwdn { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dcphy0_errb: max96712-dcphy0-errb { + rockchip,pins = <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dcphy0_lock: max96712-dcphy0-lock { + rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy0-dummy.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy0-dummy.dtsi new file mode 100644 index 000000000000..eda4f66d6f51 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy0-dummy.dtsi @@ -0,0 +1,713 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dphy0_osc: max96712-dphy0-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dphy0-osc"; + }; + + max96712_dphy0_vcc1v2: max96712-dphy0-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy0_vcc1v8: max96712-dphy0-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy0_pwdn_regulator: max96712-dphy0-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_pwdn"; + gpio = <&gpio2 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy0_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dphy0_poc_regulator: max96712-dphy0-poc0-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_poc"; + gpio = <&i2c7_nca9539_gpio 15 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dphy0_vcc12v_buck1>; + }; +}; + +&csi2_dphy0_hw { + status = "okay"; +}; + +&csi2_dphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dphy0_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy0_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi1_csi2_input>; + }; + }; + }; +}; + +&i2c7 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7m1_xfer>; + + max96712_dphy0: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dphy0_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy0_errb>, <&max96712_dphy0_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dphy0_vcc1v2>; + vcc1v8-supply = <&max96712_dphy0_vcc1v8>; + pwdn-supply = <&max96712_dphy0_pwdn_regulator>; + lock-gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dphy0_out: endpoint { + remote-endpoint = <&mipi_dphy0_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1440>; + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "disabled"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser0: max96717@51 { + compatible = "maxim,ser,max96717"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy0_cam0: dummy@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy0_ser0>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy0_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser1: max96717@52 { + compatible = "maxim,ser,max96717"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy0_cam1: dummy@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy0_ser1>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy0_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser2: max96717@53 { + compatible = "maxim,ser,max96717"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy0_cam2: dummy@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy0_ser2>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy0_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser3: max96717@54 { + compatible = "maxim,ser,max96717"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy0_cam3: dummy@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy0_ser3>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy0_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi1_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi1_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds1 { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi1_in: endpoint { + remote-endpoint = <&mipi1_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dphy0 { + max96712_dphy0_pwdn: max96712-dphy0-pwdn { + rockchip,pins = <2 RK_PA3 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dphy0_errb: max96712-dphy0-errb { + rockchip,pins = <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dphy0_lock: max96712-dphy0-lock { + rockchip,pins = <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-dummy.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-dummy.dtsi new file mode 100644 index 000000000000..dec61218dca6 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-dummy.dtsi @@ -0,0 +1,713 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dphy3_osc: max96712-dphy3-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dphy3-osc"; + }; + + max96712_dphy3_vcc1v2: max96712-dphy3-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_vcc1v8: max96712-dphy3-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_pwdn_regulator: max96712-dphy3-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_pwdn"; + gpio = <&gpio4 RK_PC0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dphy3_poc_regulator: max96712-dphy3-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_poc"; + gpio = <&gpio4 RK_PC3 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dphy3_vcc12v_buck1>; + }; +}; + +&csi2_dphy1_hw { + status = "okay"; +}; + +&csi2_dphy3 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dphy3_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy3_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy3_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi3_csi2_input>; + }; + }; + }; +}; + +&i2c8 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8m2_xfer>; + + max96712_dphy3: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dphy3_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_errb>, <&max96712_dphy3_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dphy3_vcc1v2>; + vcc1v8-supply = <&max96712_dphy3_vcc1v8>; + pwdn-supply = <&max96712_dphy3_pwdn_regulator>; + lock-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dphy3_out: endpoint { + remote-endpoint = <&mipi_dphy3_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1440>; + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "disabled"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser0: max96717@51 { + compatible = "maxim,ser,max96717"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam0: dummy@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser0>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser1: max96717@52 { + compatible = "maxim,ser,max96717"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam1: dummy@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser1>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser2: max96717@53 { + compatible = "maxim,ser,max96717"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam2: dummy@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser2>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser3: max96717@54 { + compatible = "maxim,ser,max96717"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam3: dummy@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser3>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi3_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy3_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi3_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds3 { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi3_in: endpoint { + remote-endpoint = <&mipi3_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dphy3 { + max96712_dphy3_pwdn: max96712-dphy3-pwdn { + rockchip,pins = <4 RK_PC0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dphy3_errb: max96712-dphy3-errb { + rockchip,pins = <4 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dphy3_lock: max96712-dphy3-lock { + rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-isx021.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-isx021.dtsi new file mode 100644 index 000000000000..a47c1c72e3dd --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-isx021.dtsi @@ -0,0 +1,725 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dphy3_osc: max96712-dphy3-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dphy3-osc"; + }; + + max96712_dphy3_vcc1v2: max96712-dphy3-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_vcc1v8: max96712-dphy3-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_pwdn_regulator: max96712-dphy3-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_pwdn"; + gpio = <&gpio4 RK_PC0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dphy3_poc_regulator: max96712-dphy3-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_poc"; + gpio = <&gpio4 RK_PC3 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dphy3_vcc12v_buck1>; + }; +}; + +&csi2_dphy1_hw { + status = "okay"; +}; + +&csi2_dphy3 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dphy3_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy3_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy3_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi3_csi2_input>; + }; + }; + }; +}; + +&i2c8 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8m2_xfer>; + + max96712_dphy3: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dphy3_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_errb>, <&max96712_dphy3_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dphy3_vcc1v2>; + vcc1v8-supply = <&max96712_dphy3_vcc1v8>; + pwdn-supply = <&max96712_dphy3_pwdn_regulator>; + lock-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dphy3_out: endpoint { + remote-endpoint = <&mipi_dphy3_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1281>; + crop-rect = <0 1 1920 1280>; // [ left, top, width, height ] + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "okay"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + 04 A2 00 00 00 // Master link Video 0 for frame sync generation + 04 AA 00 00 00 // Disable Vsync-Fsync overlap window + 04 AB 00 00 00 // Disable Vsync-Fsync overlap window + 04 A8 00 00 00 // FRM_DIFF_ERR_THR_L + 04 A9 00 00 00 // FRM_DIFF_ERR_THR_H + 04 A7 0c 00 00 // FSYNC_PERIOD_H, Set FSYNC period to 25M/30 clock cycles. PCLK = 25MHz. Sync freq = 30Hz + 04 A6 bf 00 00 // FSYNC_PERIOD_M + 04 A5 35 00 00 // FSYNC_PERIOD_L + 04 AF c0 00 00 // FSYNC is GMSL2 type, use osc for fsync + 04 B1 40 00 00 // FSYNC_TX_ID: set 8 to match MFP8 on serializer side + 04 A0 04 00 00 // MFP2, VS not gen internally, GPIO not used to gen fsync, manual mode + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser0: max96717@51 { + compatible = "maxim,ser,max96717f"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam0: isx021@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser0>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser1: max96717@52 { + compatible = "maxim,ser,max96717f"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam1: isx021@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser1>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser2: max96717@53 { + compatible = "maxim,ser,max96717f"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam2: isx021@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser2>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser3: max96717@54 { + compatible = "maxim,ser,max96717f"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam3: isx021@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser3>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi3_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy3_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi3_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds3 { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi3_in: endpoint { + remote-endpoint = <&mipi3_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dphy3 { + max96712_dphy3_pwdn: max96712-dphy3-pwdn { + rockchip,pins = <4 RK_PC0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dphy3_errb: max96712-dphy3-errb { + rockchip,pins = <4 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dphy3_lock: max96712-dphy3-lock { + rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; From 5b4c5525d12ffaa2d15af2d9ba71d4db80847be3 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Wed, 18 Dec 2024 19:36:29 +0800 Subject: [PATCH 15/51] media: i2c: rk628: remove unnecessary ioctl RKMODULE_GET_SKIP_FRAME Signed-off-by: Jianwei Fan Change-Id: Ib1cb58008751f335e397270e3bc62a7171ca836c --- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index 914cdd2e3c74..540e054547b6 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -2617,12 +2617,6 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) v4l2_info(sd, "user set color range: %d\n", csi->user_color_range); rk628_csi_set_color_range(sd); break; - case RKMODULE_GET_SKIP_FRAME: - if (csi->plat_data->tx_mode == DSI_MODE) - *(int *)arg = CSI_SKIP_FRAME_NORMAL; - else - *(int *)arg = 0; - break; case RK_HDMIRX_CMD_GET_EDID_VERSION: *(int *)arg = csi->edid_version; break; From 5a958179f8f9adecacdc61aa4ce7021d13fcd4d3 Mon Sep 17 00:00:00 2001 From: Jianlong Wang Date: Wed, 23 Oct 2024 09:23:02 +0800 Subject: [PATCH 16/51] arm64: configs: px30_linux_defconfig: update for kernel 6.1 Change-Id: Icfdd8be881d7fb6b971716a5eb9180507bf979b6 Signed-off-by: Jianlong Wang --- arch/arm64/configs/px30_linux_defconfig | 42 +++++++++++++------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/arch/arm64/configs/px30_linux_defconfig b/arch/arm64/configs/px30_linux_defconfig index 7add331c6fb1..91a21f48a9c4 100644 --- a/arch/arm64/configs/px30_linux_defconfig +++ b/arch/arm64/configs/px30_linux_defconfig @@ -1,3 +1,4 @@ +CONFIG_WERROR=y CONFIG_DEFAULT_HOSTNAME="localhost" CONFIG_SYSVIPC=y CONFIG_NO_HZ=y @@ -16,7 +17,6 @@ CONFIG_USER_NS=y CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_EMBEDDED=y -# CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_ARCH_ROCKCHIP=y # CONFIG_ARM64_ERRATUM_826319 is not set @@ -40,10 +40,9 @@ CONFIG_PM_ADVANCED_DEBUG=y CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y CONFIG_ENERGY_MODEL=y CONFIG_CPU_IDLE=y -CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_TIMES=y CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y @@ -51,23 +50,15 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPUFREQ_DT=y CONFIG_ARM_ROCKCHIP_CPUFREQ=y -CONFIG_ARM_SCMI_PROTOCOL=y -CONFIG_ROCKCHIP_SIP=y -CONFIG_ARM64_CRYPTO=y -CONFIG_CRYPTO_SHA1_ARM64_CE=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y +# CONFIG_COMPAT_BRK is not set # CONFIG_COMPACTION is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 CONFIG_CMA=y -CONFIG_ZSMALLOC=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -103,6 +94,8 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_DEBUG_DEVRES=y CONFIG_CONNECTOR=y +CONFIG_ARM_SCMI_PROTOCOL=y +CONFIG_ROCKCHIP_SIP=y CONFIG_DTC_SYMBOLS=y CONFIG_ZRAM=y CONFIG_BLK_DEV_LOOP=y @@ -218,14 +211,12 @@ CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK808=y CONFIG_MEDIA_SUPPORT=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y # CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV is not set -# CONFIG_USB_GSPCA is not set CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_VIDEO_ROCKCHIP_RKISP1=y CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_ROCKCHIP_RKISP1=y CONFIG_VIDEO_OV5695=y # CONFIG_DVB_AU8522_V4L is not set # CONFIG_DVB_TUNER_DIB0070 is not set @@ -273,7 +264,6 @@ CONFIG_UHID=y CONFIG_HID_KENSINGTON=y CONFIG_HID_MULTITOUCH=y CONFIG_USB_HIDDEV=y -CONFIG_I2C_HID=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y # CONFIG_USB_DEFAULT_PERSIST is not set CONFIG_USB_OTG=y @@ -319,6 +309,10 @@ CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_RK808=y CONFIG_DMADEVICES=y CONFIG_PL330_DMA=y +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_SYSFS_STATS=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMABUF_HEAPS_CMA=y CONFIG_STAGING=y CONFIG_COMMON_CLK_RK808=y CONFIG_COMMON_CLK_SCMI=y @@ -338,6 +332,9 @@ CONFIG_FIQ_DEBUGGER=y CONFIG_FIQ_DEBUGGER_NO_SLEEP=y CONFIG_FIQ_DEBUGGER_CONSOLE=y CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE=y +CONFIG_FIQ_DEBUGGER_TRUST_ZONE=y +CONFIG_RK_CONSOLE_THREAD=y +CONFIG_ROCKCHIP_DEBUG=y CONFIG_PM_DEVFREQ=y CONFIG_DEVFREQ_GOV_PERFORMANCE=y CONFIG_DEVFREQ_GOV_POWERSAVE=y @@ -357,7 +354,6 @@ CONFIG_PWM_ROCKCHIP=y CONFIG_PHY_ROCKCHIP_CSI2_DPHY=y CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y -CONFIG_ANDROID=y CONFIG_NVMEM_ROCKCHIP_OTP=y CONFIG_RK_HEADSET=y CONFIG_EXT4_FS=y @@ -391,12 +387,17 @@ CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y CONFIG_SECURITYFS=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRC_CCITT=y CONFIG_CRC_T10DIF=y CONFIG_CRC7=y @@ -407,9 +408,10 @@ CONFIG_CRC7=y CONFIG_DMA_CMA=y CONFIG_PRINTK_TIME=y CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0 +# CONFIG_SLUB_DEBUG is not set CONFIG_SOFTLOCKUP_DETECTOR=y CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y From fce333a285345492799868444046fb2538e367ba Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Fri, 20 Dec 2024 11:54:42 +0800 Subject: [PATCH 17/51] nvmem: rockchip-otp: Remove redundant clocks Change-Id: Ifecc210da1687ae3f85e1c11a2082f125cb61fdb Signed-off-by: Finley Xiao --- drivers/nvmem/rockchip-otp.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c index d5c5d6658f8b..981b78418453 100644 --- a/drivers/nvmem/rockchip-otp.c +++ b/drivers/nvmem/rockchip-otp.c @@ -783,21 +783,17 @@ static const struct rockchip_data rk3528_data = { .reg_read = rk3568_otp_read, }; -static const char * const rk3562_otp_clocks[] = { +static const char * const rk3568_otp_clocks[] = { "usr", "sbpi", "apb", "phy", }; static const struct rockchip_data rk3562_data = { .size = 0x80, - .clocks = rk3562_otp_clocks, - .num_clks = ARRAY_SIZE(rk3562_otp_clocks), + .clocks = rk3568_otp_clocks, + .num_clks = ARRAY_SIZE(rk3568_otp_clocks), .reg_read = rk3568_otp_read, }; -static const char * const rk3568_otp_clocks[] = { - "usr", "sbpi", "apb", "phy", -}; - static const struct rockchip_data rk3568_data = { .size = 0x80, .clocks = rk3568_otp_clocks, @@ -829,14 +825,10 @@ static const struct rockchip_data rk3588_data = { .reg_read = rk3588_otp_read, }; -static const char * const rv1106_otp_clocks[] = { - "usr", "sbpi", "apb", "phy", -}; - static const struct rockchip_data rv1106_data = { .size = 0x80, - .clocks = rv1106_otp_clocks, - .num_clks = ARRAY_SIZE(rv1106_otp_clocks), + .clocks = rk3568_otp_clocks, + .num_clks = ARRAY_SIZE(rk3568_otp_clocks), .reg_read = rk3568_otp_read, }; From 629b36c6b3f4166368deb56e168699419d2bf19b Mon Sep 17 00:00:00 2001 From: Zhihuan He Date: Fri, 22 Nov 2024 17:07:07 +0800 Subject: [PATCH 18/51] memory: rockchip: dsmc: set 0.5x refresh rate allow for xccela psram Change-Id: I3195579b8c1d597f25e0a9711cd3edc5a6599ab4 Signed-off-by: Zhihuan He --- drivers/memory/rockchip/dsmc-controller.c | 3 +++ drivers/memory/rockchip/dsmc-host.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/memory/rockchip/dsmc-controller.c b/drivers/memory/rockchip/dsmc-controller.c index d4e85f85cdc9..495f8a3820fb 100644 --- a/drivers/memory/rockchip/dsmc-controller.c +++ b/drivers/memory/rockchip/dsmc-controller.c @@ -507,6 +507,9 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) mr_tmp = (mr_tmp & (~(XCCELA_MR4_WL_MASK << XCCELA_MR4_WL_SHIFT))) | (tmp << XCCELA_MR4_WL_SHIFT); + /* set 0.5x refresh rate allow */ + mr_tmp = (mr_tmp & (~(XCCELA_MR4_REFRESH_MASK << XCCELA_MR4_REFRESH_SHIFT))) | + (XCCELA_MR4_0_5_REFRESH_RATE << XCCELA_MR4_REFRESH_SHIFT); xccela_write_mr(region_map, 4, mr_tmp); diff --git a/drivers/memory/rockchip/dsmc-host.h b/drivers/memory/rockchip/dsmc-host.h index 9e4f7671a594..0c17d7eafd79 100644 --- a/drivers/memory/rockchip/dsmc-host.h +++ b/drivers/memory/rockchip/dsmc-host.h @@ -254,6 +254,9 @@ #define XCCELA_MR4_WL_SHIFT (5) #define XCCELA_MR4_WL_MASK (0x7) +#define XCCELA_MR4_REFRESH_SHIFT (3) +#define XCCELA_MR4_REFRESH_MASK (0x3) +#define XCCELA_MR4_0_5_REFRESH_RATE (0x3) #define XCCELA_MR8_IO_TYPE_SHIFT (6) #define XCCELA_MR8_IO_TYPE_MASK (0x1) From 58231cec6bc95cbbec24abe8e87a29ada06e8c15 Mon Sep 17 00:00:00 2001 From: Zhihuan He Date: Wed, 18 Dec 2024 17:00:54 +0800 Subject: [PATCH 19/51] memory: rockchip: dsmc: fix io width config error The io_width in diff cs should set the same value at the same time. Change-Id: I2a872ba487bde9aa56f0a3490acbb526a1521475 Signed-off-by: Zhihuan He --- drivers/memory/rockchip/dsmc-controller.c | 139 +++++++++++++--------- drivers/memory/rockchip/dsmc-host.c | 38 +++++- 2 files changed, 118 insertions(+), 59 deletions(-) diff --git a/drivers/memory/rockchip/dsmc-controller.c b/drivers/memory/rockchip/dsmc-controller.c index 495f8a3820fb..1dc29ecf599d 100644 --- a/drivers/memory/rockchip/dsmc-controller.c +++ b/drivers/memory/rockchip/dsmc-controller.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include @@ -110,19 +111,21 @@ static uint32_t cap_2_dev_size(uint32_t cap) static int dsmc_psram_id_detect(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t tmp, i; + uint32_t tmp[DSMC_MAX_SLAVE_NUM], i; int ret = -1; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; - tmp = readl(dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + tmp[i] = readl(dsmc->regs + DSMC_MCR(i)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } if (cfg->protcl == OPI_XCCELA_PSRAM) { uint8_t mid; @@ -157,15 +160,17 @@ static int dsmc_psram_id_detect(struct rockchip_dsmc *dsmc, uint32_t cs) } } - /* config to memory space */ - writel(tmp, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(tmp[i], dsmc->regs + DSMC_MCR(i)); return ret; } static void dsmc_psram_bw_detect(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t tmp, col; + uint32_t i; + uint32_t tmp[DSMC_MAX_SLAVE_NUM], col; uint16_t ir0_ir1; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; @@ -177,13 +182,15 @@ static void dsmc_psram_bw_detect(struct rockchip_dsmc *dsmc, uint32_t cs) else cfg->io_width = MCR_IOWIDTH_X8; } else { - tmp = readl(dsmc->regs + DSMC_MCR(cs)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + tmp[i] = readl(dsmc->regs + DSMC_MCR(i)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } /* hyper psram get IR0 */ ir0_ir1 = hyper_read_mr(region_map, HYPER_PSRAM_IR0); @@ -195,8 +202,9 @@ static void dsmc_psram_bw_detect(struct rockchip_dsmc *dsmc, uint32_t cs) else cfg->io_width = MCR_IOWIDTH_X8; - /* config to memory space */ - writel(tmp, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(tmp[i], dsmc->regs + DSMC_MCR(i)); } cfg->col = col; @@ -206,6 +214,7 @@ static int dsmc_psram_dectect(struct rockchip_dsmc *dsmc, uint32_t cs) { uint32_t i = 0; int ret = -1; + struct device *dev = dsmc->dev; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; /* axi read do not response error */ @@ -229,7 +238,7 @@ static int dsmc_psram_dectect(struct rockchip_dsmc *dsmc, uint32_t cs) cfg->protcl = psram_info[i].protcl; cfg->mtr_timing = psram_info[i].mtr_timing; if (!dsmc_psram_id_detect(dsmc, cs)) { - pr_info("DSMC: The cs%d %s PSRAM ID: 0x%x\n", cs, + dev_info(dev, "The cs%d %s PSRAM ID: 0x%x\n", cs, (cfg->protcl == OPI_XCCELA_PSRAM) ? "XCCELA" : "HYPER", psram_info[i].id); ret = 0; @@ -237,7 +246,7 @@ static int dsmc_psram_dectect(struct rockchip_dsmc *dsmc, uint32_t cs) } } if (i == ARRAY_SIZE(psram_info)) { - pr_err("DSMC: Unknown PSRAM device\n"); + dev_err(dev, "Unknown PSRAM device\n"); ret = -1; } else { dsmc_psram_bw_detect(dsmc, cs); @@ -315,6 +324,7 @@ static int dsmc_slv_cmn_rgn_config(struct rockchip_dsmc *dsmc, uint32_t rgn, uint32_t cs) { uint32_t tmp; + struct device *dev = dsmc->dev; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; @@ -324,21 +334,21 @@ static int dsmc_slv_cmn_rgn_config(struct rockchip_dsmc *dsmc, } else if (slv_rgn->dummy_clk_num == 1) { tmp |= slv_rgn->dummy_clk_num << WR_DATA_CYC_EXTENDED_SHIFT; } else { - pr_err("DSMC: lb slave: dummy clk too large\n"); + dev_err(dev, "lb slave: dummy clk too large\n"); return -1; } tmp &= ~(RD_LATENCY_CYC_MASK << RD_LATENCY_CYC_SHIFT); if ((cfg->rd_latency == 1) || (cfg->rd_latency == 2)) { tmp |= cfg->rd_latency << RD_LATENCY_CYC_SHIFT; } else { - pr_err("DSMC: lb slave: read latency value error\n"); + dev_err(dev, "lb slave: read latency value error\n"); return -1; } tmp &= ~(WR_LATENCY_CYC_MASK << WR_LATENCY_CYC_SHIFT); if ((cfg->wr_latency == 1) || (cfg->wr_latency == 2)) { tmp |= cfg->wr_latency << WR_LATENCY_CYC_SHIFT; } else { - pr_err("DSMC: lb slave: write latency value error\n"); + dev_err(dev, "lb slave: write latency value error\n"); return -1; } tmp &= ~(CA_CYC_MASK << CA_CYC_SHIFT); @@ -356,6 +366,7 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc, struct regions_config *slv_rgn, uint32_t cs) { uint32_t tmp; + struct device *dev = dsmc->dev; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; @@ -371,7 +382,7 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc, } else if (slv_rgn->dummy_clk_num == 1) { tmp |= slv_rgn->dummy_clk_num << WR_DATA_CYC_EXTENDED_SHIFT; } else { - pr_err("DSMC: lb slave: dummy clk too large\n"); + dev_err(dev, "lb slave: dummy clk too large\n"); return -1; } @@ -388,18 +399,20 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc, static int dsmc_lb_cmn_config(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t tmp, i; + uint32_t tmp[DSMC_MAX_SLAVE_NUM], i; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; struct regions_config *slv_rgn; int ret = 0; - tmp = readl(dsmc->regs + DSMC_MCR(cs)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + tmp[i] = readl(dsmc->regs + DSMC_MCR(i)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } for (i = 0; i < DSMC_LB_MAX_RGN; i++) { slv_rgn = &cfg->slv_rgn[i]; @@ -413,8 +426,9 @@ static int dsmc_lb_cmn_config(struct rockchip_dsmc *dsmc, uint32_t cs) slv_rgn = &cfg->slv_rgn[0]; ret = dsmc_slv_cmn_config(dsmc, slv_rgn, cs); - /* config to memory space */ - writel(tmp, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(tmp[i], dsmc->regs + DSMC_MCR(i)); for (i = 0; i < DSMC_LB_MAX_RGN; i++) { slv_rgn = &cfg->slv_rgn[i]; @@ -472,17 +486,20 @@ static void dsmc_cfg_latency(uint32_t rd_ltcy, uint32_t wr_ltcy, static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t latency, mcr, tmp; + uint32_t i; + uint32_t latency, mcr[DSMC_MAX_SLAVE_NUM], tmp; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cs_cfg = &dsmc->cfg.cs_cfg[cs]; - mcr = readl(dsmc->regs + DSMC_MCR(cs)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + mcr[i] = readl(dsmc->regs + DSMC_MCR(i)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } if (cs_cfg->protcl == OPI_XCCELA_PSRAM) { /* Xccela psram init */ uint8_t mr_tmp, rbxen; @@ -586,8 +603,9 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) (CR1_CLOCK_TYPE_DIFF_CLK << CR1_CLOCK_TYPE_SHIFT); hyper_write_mr(region_map, HYPER_PSRAM_CR1, cr_tmp); } - /* config to memory space */ - writel(mcr, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(mcr[i], dsmc->regs + DSMC_MCR(i)); return 0; } @@ -596,6 +614,7 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) static int dsmc_psram_init(struct rockchip_dsmc *dsmc, uint32_t cs) { uint32_t latency; + struct device *dev = dsmc->dev; struct dsmc_config_cs *cs_cfg = &dsmc->cfg.cs_cfg[cs]; uint32_t mhz = dsmc->cfg.freq_hz / MHZ; @@ -610,7 +629,7 @@ static int dsmc_psram_init(struct rockchip_dsmc *dsmc, uint32_t cs) } else if (mhz <= 200) { latency = 7; } else { - pr_err("DSMC: PSRAM frequency do not support!\n"); + dev_err(dev, "PSRAM frequency do not support!\n"); return -1; } @@ -649,6 +668,7 @@ static int dsmc_ctrller_cfg_for_psram(struct rockchip_dsmc *dsmc, uint32_t cs) static void dsmc_psram_remodify_timing(struct rockchip_dsmc *dsmc, uint32_t cs) { + uint32_t i; uint32_t max_length = 511, tcmd = 3; uint32_t tcsm, tmp; uint32_t mhz = dsmc->cfg.freq_hz / MHZ; @@ -673,13 +693,16 @@ static void dsmc_psram_remodify_timing(struct rockchip_dsmc *dsmc, uint32_t cs) if (tmp > max_length) tmp = max_length; + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT, + cs_cfg->io_width << MCR_IOWIDTH_SHIFT); + REG_CLRSETBITS(dsmc, DSMC_MCR(cs), (MCR_MAXEN_MASK << MCR_MAXEN_SHIFT) | - (MCR_MAXLEN_MASK << MCR_MAXLEN_SHIFT) | - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT), + (MCR_MAXLEN_MASK << MCR_MAXLEN_SHIFT), (MCR_MAX_LENGTH_EN << MCR_MAXEN_SHIFT) | - (tmp << MCR_MAXLEN_SHIFT) | - (cs_cfg->io_width << MCR_IOWIDTH_SHIFT)); + (tmp << MCR_MAXLEN_SHIFT)); if (cs_cfg->io_width == MCR_IOWIDTH_X16) tmp = cs_cfg->col - 2; @@ -797,6 +820,7 @@ int rockchip_dsmc_dll_training(struct rockchip_dsmc_device *priv) int dll, dll_step = 10; struct dsmc_config_cs *cfg; struct rockchip_dsmc *dsmc = &priv->dsmc; + struct device *dev = dsmc->dev; int ret; for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) { @@ -832,11 +856,11 @@ int rockchip_dsmc_dll_training(struct rockchip_dsmc_device *priv) } dll = (dll_max + dll_min) / 2; if ((dll >= 0xff) || (dll <= 0)) { - pr_err("DSMC: cs%d byte%d dll training error(0x%x)\n", + dev_err(dev, "DSMC: cs%d byte%d dll training error(0x%x)\n", cs, byte, dll); return -1; } - pr_info("DSMC: cs%d byte%d dll delay line result 0x%x\n", cs, byte, dll); + dev_info(dev, "cs%d byte%d dll delay line result 0x%x\n", cs, byte, dll); REG_CLRSETBITS(dsmc, DSMC_RDS_DLL_CTL(cs, byte), RDS_DLL0_CTL_RDS_0_CLK_DELAY_NUM_MASK, dll << RDS_DLL0_CTL_RDS_0_CLK_DELAY_NUM_SHIFT); @@ -945,6 +969,7 @@ EXPORT_SYMBOL(rockchip_dsmc_psram_reinit); int rockchip_dsmc_ctrller_init(struct rockchip_dsmc *dsmc, uint32_t cs) { + uint32_t i; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; writel(MRGTCR_READ_WRITE_MERGE_EN, @@ -956,17 +981,21 @@ int rockchip_dsmc_ctrller_init(struct rockchip_dsmc *dsmc, uint32_t cs) (cfg->dll_num[1] << RDS_DLL1_CTL_RDS_1_CLK_DELAY_NUM_SHIFT), dsmc->regs + DSMC_RDS_DLL1_CTL(cs)); + /* all io_width should set the same value in diff cs */ + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + REG_CLRSETBITS(dsmc, DSMC_MCR(cs), + MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT, + cfg->io_width << MCR_IOWIDTH_SHIFT); + REG_CLRSETBITS(dsmc, DSMC_MCR(cs), (MCR_ACS_MASK << MCR_ACS_SHIFT) | (MCR_DEVTYPE_MASK << MCR_DEVTYPE_SHIFT) | - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | (MCR_EXCLUSIVE_DQS_MASK << MCR_EXCLUSIVE_DQS_SHIFT) | (MCR_WRAPSIZE_MASK << MCR_WRAPSIZE_SHIFT) | (MCR_MAXEN_MASK << MCR_MAXEN_SHIFT) | (MCR_MAXLEN_MASK << MCR_MAXLEN_SHIFT), (cfg->acs << MCR_ACS_SHIFT) | (MCR_DEVTYPE_HYPERRAM << MCR_DEVTYPE_SHIFT) | - (cfg->io_width << MCR_IOWIDTH_SHIFT) | (cfg->exclusive_dqs << MCR_EXCLUSIVE_DQS_SHIFT) | (cfg->wrap_size << MCR_WRAPSIZE_SHIFT) | (cfg->max_length_en << MCR_MAXEN_SHIFT) | diff --git a/drivers/memory/rockchip/dsmc-host.c b/drivers/memory/rockchip/dsmc-host.c index b96e012d395d..03e4ff3b3189 100644 --- a/drivers/memory/rockchip/dsmc-host.c +++ b/drivers/memory/rockchip/dsmc-host.c @@ -526,6 +526,7 @@ static int dsmc_write(struct rockchip_dsmc_device *dsmc_dev, uint32_t cs, uint32 static void dsmc_lb_dma_hw_mode_en(struct rockchip_dsmc *dsmc, uint32_t cs) { + struct device *dev = dsmc->dev; struct dsmc_transfer *xfer = &dsmc->xfer; size_t size = xfer->transfer_size; uint32_t burst_byte = xfer->brst_len * xfer->brst_size; @@ -533,7 +534,7 @@ static void dsmc_lb_dma_hw_mode_en(struct rockchip_dsmc *dsmc, uint32_t cs) dma_req_num = size / burst_byte; if (size % burst_byte) { - pr_warn("DSMC: DMA size is unaligned\n"); + dev_warn(dev, "DMA size is unaligned\n"); dma_req_num++; } writel(dma_req_num, dsmc->regs + DSMC_DMA_REQ_NUM(cs)); @@ -683,7 +684,7 @@ static int dsmc_copy_from(struct rockchip_dsmc_device *dsmc_dev, uint32_t cs, ui struct rockchip_dsmc *dsmc = &dsmc_dev->dsmc; if (atomic_read(&dsmc->xfer.state) & (RXDMA | TXDMA)) { - pr_warn("DSMC: copy_from: the transfer is busy!\n"); + dev_warn(dev, "copy_from: the transfer is busy!\n"); return -EBUSY; } @@ -721,7 +722,7 @@ static int dsmc_copy_to(struct rockchip_dsmc_device *dsmc_dev, uint32_t cs, uint struct rockchip_dsmc *dsmc = &dsmc_dev->dsmc; if (atomic_read(&dsmc->xfer.state) & (RXDMA | TXDMA)) { - pr_warn("DSMC: copy_to: the transfer is busy!\n"); + dev_warn(dev, "copy_to: the transfer is busy!\n"); return -EBUSY; } @@ -785,6 +786,29 @@ static void dsmc_data_init(struct rockchip_dsmc *dsmc) } } +static int dsmc_check_mult_psram_cap(struct rockchip_dsmc *dsmc) +{ + uint32_t cs; + uint32_t io_width = 0xffffffff; + struct device *dev = dsmc->dev; + struct dsmc_ctrl_config *cfg = &dsmc->cfg; + + for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) { + if (cfg->cs_cfg[cs].device_type == DSMC_UNKNOWN_DEVICE) + continue; + if (io_width == 0xffffffff) { + io_width = dsmc->cfg.cs_cfg[cs].io_width; + } else { + if (io_width != dsmc->cfg.cs_cfg[cs].io_width) { + dev_err(dev, "The io width error for mult rank!\n"); + return -1; + } + } + } + + return 0; +} + static void dsmc_reset_ctrl(struct rockchip_dsmc *dsmc) { reset_control_assert(dsmc->areset); @@ -797,6 +821,7 @@ static void dsmc_reset_ctrl(struct rockchip_dsmc *dsmc) static int dsmc_init(struct rockchip_dsmc *dsmc) { uint32_t cs; + struct device *dev = dsmc->dev; struct dsmc_ctrl_config *cfg = &dsmc->cfg; struct dsmc_config_cs *cs_cfg; uint32_t ret = 0; @@ -812,13 +837,18 @@ static int dsmc_init(struct rockchip_dsmc *dsmc) return ret; } } + + ret = dsmc_check_mult_psram_cap(dsmc); + if (ret) + return ret; + dsmc_reset_ctrl(dsmc); for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) { if (cfg->cs_cfg[cs].device_type == DSMC_UNKNOWN_DEVICE) continue; cs_cfg = &dsmc->cfg.cs_cfg[cs]; - pr_info("DSMC: init cs%d %s device\n", + dev_info(dev, "init cs%d %s device\n", cs, (cs_cfg->device_type == DSMC_LB_DEVICE) ? "LB" : "PSRAM"); rockchip_dsmc_ctrller_init(dsmc, cs); if (cs_cfg->device_type == OPI_XCCELA_PSRAM) From 7fdaaa54f698fae8072efca5f2d86dd5764238fa Mon Sep 17 00:00:00 2001 From: Zhihuan He Date: Wed, 18 Dec 2024 17:36:54 +0800 Subject: [PATCH 20/51] ARM: dts: rockchip: rk3506-pinctrl: set dsmc clk drive strength to L3 Change-Id: I097abc26413ea50d1e3c56ae57a7d014a8bfcf46 Signed-off-by: Zhihuan He --- arch/arm/boot/dts/rk3506-pinctrl.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3506-pinctrl.dtsi b/arch/arm/boot/dts/rk3506-pinctrl.dtsi index 0da9f08b27f1..7f6c6b89a24c 100644 --- a/arch/arm/boot/dts/rk3506-pinctrl.dtsi +++ b/arch/arm/boot/dts/rk3506-pinctrl.dtsi @@ -101,7 +101,7 @@ dsmc_clk_pins: dsmc-clk-pins { rockchip,pins = /* dsmc_clkn */ - <1 RK_PA1 2 &pcfg_pull_up>, + <1 RK_PA1 2 &pcfg_pull_up_drv_level_3>, /* dsmc_resetn */ <1 RK_PC0 2 &pcfg_pull_up>; }; @@ -123,7 +123,7 @@ dsmc_bus16_pins: dsmc-bus16-pins { rockchip,pins = /* dsmc_clkp */ - <1 RK_PA0 2 &pcfg_pull_down>, + <1 RK_PA0 2 &pcfg_pull_down_drv_level_3>, /* dsmc_d0 */ <1 RK_PA3 2 &pcfg_pull_down>, /* dsmc_d1 */ From 7bc0d73f22abf63d9b81a3dfcec47f083d9d1c0a Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Thu, 19 Dec 2024 09:50:57 +0800 Subject: [PATCH 21/51] drm/rockchip: bridge: analogix_dp: fix the regs settings for TEST_PATTERN_80BIT According to the DP PHY CTS v1.2b 3.2.3 and 3.3.3 chapters, the PreEmphasis Level Test Pattern(PLTPAT), which also was called 80-bit custom pattern, should be: 1111100000 1111100000 1111100000 1111100000 1111100000 1111100000 1111100000 1111100000 It is used to verify the HBR2 in "Non Pre-Emphasis Level Verification Testing" and "Pre-Emphasis Level Verification and Maximum Pk-Pk Differential Voltage Testing". Without this patch, the PLTPAT pattern is incorrect. Fixes: 304dbb104da1 ("drm/bridge: analogix_dp: Add DP Test Automation") Change-Id: I4b00acd0a360a8ba3f3eaf32fb30e0a18a451f5c Signed-off-by: Damon Ding --- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 83ff85d873a9..8b89e45d2fda 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -738,9 +738,9 @@ void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, case TEST_PATTERN_80BIT: reg = 0x3e0f83e0; analogix_dp_write(dp, ANALOGIX_DP_TEST_80B_PATTERN0, reg); - reg = 0x0f83e0f8; + reg = 0x3e0f83e0; analogix_dp_write(dp, ANALOGIX_DP_TEST_80B_PATTERN1, reg); - reg = 0x0000f83e; + reg = 0x000f83e0; analogix_dp_write(dp, ANALOGIX_DP_TEST_80B_PATTERN2, reg); reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_80BIT; analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg); From ee40bbe630856820beb6070cae8a51e5f4083689 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Mon, 18 Nov 2024 11:38:57 +0800 Subject: [PATCH 22/51] drm/rockchip: dw-dp: update gpio hpd state when init stage The gpio hpd state will be mismatch the real state if the cable plug before init the dp controller. So it need updage the gpio hpd state when dp controller init. Fixes: 601aff23373b ("drm/rockchip: dw-dp: optimize the logic to deal with hpd") Change-Id: I6b7a3d88e2ef70e54ad9465859c1a55205f10c4f Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/dw-dp.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index a7400bf99953..ea9e6335b2d0 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -2843,7 +2843,6 @@ static irqreturn_t dw_dp_hpd_irq_handler(int irq, void *arg) dp->hotplug.long_hpd = true; dp->hotplug.status = hpd; dp->hotplug.state = GPIO_STATE_PLUG; - schedule_work(&dp->hpd_work); } } else if (dp->hotplug.state == GPIO_STATE_PLUG) { if (!hpd) { @@ -2858,9 +2857,12 @@ static irqreturn_t dw_dp_hpd_irq_handler(int irq, void *arg) dp->hotplug.long_hpd = false; dp->hotplug.status = hpd; dp->hotplug.state = GPIO_STATE_PLUG; - schedule_work(&dp->hpd_work); } } + + if (hpd) + schedule_work(&dp->hpd_work); + mutex_unlock(&dp->irq_lock); @@ -2870,6 +2872,10 @@ static irqreturn_t dw_dp_hpd_irq_handler(int irq, void *arg) static void dw_dp_hpd_init(struct dw_dp *dp) { dp->hotplug.status = dw_dp_detect_no_power(dp); + if (dp->hpd_gpio && dp->hotplug.status) { + dp->hotplug.state = GPIO_STATE_PLUG; + dp->hotplug.long_hpd = true; + } if (dp->hpd_gpio || dp->force_hpd || dp->usbdp_hpd) { regmap_update_bits(dp->regmap, DPTX_CCTL, FORCE_HPD, From 0ebac7251aa188027460d41994dee3d69337b7c9 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Tue, 17 Dec 2024 10:58:34 +0800 Subject: [PATCH 23/51] drm/rockchip: vop2: wait dp output config take effect The dp_out_en is config as take effect by vsync signal. When disable the output, it will do some thing as follow: 1. clean dp_out_en bit in vop. 2. disable dp video stream; 3. disable dp link clk. If it not wait clean dp_out_en bit take effect, the link clk may disable before clean dp_out_en bit, which will cause dp fifo overflow issue. When enable the output, though it not has this issue, it's better to wait set dp_out_en bit take effect to avoid the similar issue in the future. Change-Id: Ie088a0265e5bdef349cdd3e0dc3daebb6d9eeeff Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 9598b4624cee..25f3879a46b0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1038,6 +1038,9 @@ static const struct drm_bus_format_enum_list drm_bus_format_enum_list[] = { static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list) +static inline void vop2_cfg_done(struct drm_crtc *crtc); +static void vop2_wait_for_fs_by_done_bit_status(struct vop2_video_port *vp); + static inline struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc) { struct rockchip_crtc *rockchip_crtc; @@ -1224,7 +1227,12 @@ static void vop2_crtc_output_post_enable(struct drm_crtc *crtc, int intf) else if (intf & VOP_OUTPUT_IF_DP2) VOP_CTRL_SET(vop2, dp2_en, 1); - dev_info(vop2->dev, "vop enable intf:%x\n", intf); + if (output_if_is_dp(intf)) { + vop2_cfg_done(crtc); + vop2_wait_for_fs_by_done_bit_status(vp); + } + + drm_info(vop2, "vop enable intf:%x\n", intf); } static void vop2_crtc_output_pre_disable(struct drm_crtc *crtc, int intf) @@ -1239,7 +1247,12 @@ static void vop2_crtc_output_pre_disable(struct drm_crtc *crtc, int intf) else if (intf & VOP_OUTPUT_IF_DP2) VOP_CTRL_SET(vop2, dp2_en, 0); - dev_info(vop2->dev, "vop disable intf:%x\n", intf); + if (output_if_is_dp(intf)) { + vop2_cfg_done(crtc); + vop2_wait_for_fs_by_done_bit_status(vp); + } + + drm_info(vop2, "vop disable intf:%x\n", intf); } static inline const struct vop2_win_regs *vop2_get_win_regs(struct vop2_win *win, From f14e8a23fc27037e4ce26fedd8a44ba85f75b905 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 17:32:31 +0800 Subject: [PATCH 24/51] boot.its: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: If4996bba54ba14fc09a25eab93882bcc2a7a2876 --- boot.its | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot.its b/boot.its index 755005c424b4..648258fde2dc 100644 --- a/boot.its +++ b/boot.its @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Rockchip Electronics Co., Ltd + * Copyright (C) 2021 Rockchip Electronics Co., Ltd. * * SPDX-License-Identifier: GPL-2.0 */ From f15e2190c8bdff265b3c4b366a2c6bede6dbfb1b Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 17:33:44 +0800 Subject: [PATCH 25/51] arm64: mm: fixup_fault: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: Ife97e80bb3161b5cb3083d68aaa5098bf7df33df --- arch/arm64/mm/fixup_fault.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/mm/fixup_fault.S b/arch/arm64/mm/fixup_fault.S index 0e94564ae68d..2ee99f3f74b0 100644 --- a/arch/arm64/mm/fixup_fault.S +++ b/arch/arm64/mm/fixup_fault.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2023 Rockchip Electronics Co. Ltd. + * Copyright (C) 2023 Rockchip Electronics Co., Ltd. */ .arch armv8-a From 2c9cb1d9438eef1fb8400522bd20a536a80e868e Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 17:35:32 +0800 Subject: [PATCH 26/51] PM / devfreq: rockchip_dmc: Fix typos in Rockchip copyright notices Signed-off-by: Tao Huang Change-Id: I9140e17cf732b9c0d95509a661592fad2810b362 --- drivers/devfreq/rockchip_dmc.c | 2 +- drivers/devfreq/rockchip_dmc_common.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index c798f9220ed7..3526ebc1ecc7 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -2,7 +2,7 @@ /* * Rockchip Generic dmc support. * - * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. * Author: Finley Xiao */ diff --git a/drivers/devfreq/rockchip_dmc_common.c b/drivers/devfreq/rockchip_dmc_common.c index 7765e7174ce2..9fcf4583812a 100644 --- a/drivers/devfreq/rockchip_dmc_common.c +++ b/drivers/devfreq/rockchip_dmc_common.c @@ -2,7 +2,7 @@ /* * Rockchip dmc common functions. * - * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. * Author: Finley Xiao */ From f2dff6de3ef7060eb0c3506128471215dacf2411 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 17:36:45 +0800 Subject: [PATCH 27/51] gpio: aw9110: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: Ifda4695da966586a409ac4069aa232df43863551 --- drivers/gpio/gpio-aw9110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-aw9110.c b/drivers/gpio/gpio-aw9110.c index ab97726fc7ce..b68bd866b9ff 100644 --- a/drivers/gpio/gpio-aw9110.c +++ b/drivers/gpio/gpio-aw9110.c @@ -2,7 +2,7 @@ /* * Driver for aw9110 I2C GPIO expanders * - * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. */ #include #include From 7c14384384b379e0c79699619bf5d92d55c9b28c Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 17:37:26 +0800 Subject: [PATCH 28/51] gpio: rockchip: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: Iab2fb03e9db190a8456d0bca5df0b1653c56fcf0 --- drivers/gpio/gpio-rockchip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index 4a0c12a2808d..2869a50c16be 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -3,7 +3,7 @@ * Copyright (c) 2013 MundoReader S.L. * Author: Heiko Stuebner * - * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. */ #include From 7f19b48064fc55bd2fa8f782fdfdac6cd69e4dee Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 17:38:37 +0800 Subject: [PATCH 29/51] MALI: bifrost: Fix typos in Rockchip copyright notices Signed-off-by: Tao Huang Change-Id: I33e9cc6a988e96bd37a446bd02c2657688ede13f --- drivers/gpu/arm/bifrost/platform/rk/custom_log.h | 2 +- drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/arm/bifrost/platform/rk/custom_log.h b/drivers/gpu/arm/bifrost/platform/rk/custom_log.h index 5de70ee13d25..fedfd41bb511 100755 --- a/drivers/gpu/arm/bifrost/platform/rk/custom_log.h +++ b/drivers/gpu/arm/bifrost/platform/rk/custom_log.h @@ -1,5 +1,5 @@ /* - * (C) COPYRIGHT RockChip Limited. All rights reserved. + * (C) COPYRIGHT Rockchip Electronics Co., Ltd. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software diff --git a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c index cb3f6979bb5d..d20de78ce478 100755 --- a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c +++ b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c @@ -1,5 +1,5 @@ /* - * (C) COPYRIGHT RockChip Limited. All rights reserved. + * (C) COPYRIGHT Rockchip Electronics Co., Ltd. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software From 791a51855b52f9cb24a7a10f754bf1fe8be4e4a0 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 17:40:06 +0800 Subject: [PATCH 30/51] Mali: utgard: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: I789d8239c08ef8b2086477b40164a2007470a1fb --- drivers/gpu/arm/mali400/mali/platform/rk/rk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/arm/mali400/mali/platform/rk/rk.c b/drivers/gpu/arm/mali400/mali/platform/rk/rk.c index edbdf8b5f0f7..7f0e160cb1b4 100644 --- a/drivers/gpu/arm/mali400/mali/platform/rk/rk.c +++ b/drivers/gpu/arm/mali400/mali/platform/rk/rk.c @@ -1,5 +1,5 @@ /* - * (C) COPYRIGHT RockChip Limited. All rights reserved. + * (C) COPYRIGHT Rockchip Electronics Co., Ltd. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software From f81381b769dcdb18611c2f945a532c2944150547 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 18:12:03 +0800 Subject: [PATCH 31/51] Revert "SDMMC: Complete submission SDMMC driver in kernel-3.10.Currently,Only the sdcard can be used." This reverts commit 3afdc6aaef3b91e06e59fb35e90d48fc69e747ae. This driver is unused since linux 4.4, drop it. Signed-off-by: Tao Huang Change-Id: I2f2260816aaf3637713b811c292673158ab4a981 --- drivers/mmc/host/rk_sdmmc.h | 387 ------------------------------------ 1 file changed, 387 deletions(-) delete mode 100755 drivers/mmc/host/rk_sdmmc.h diff --git a/drivers/mmc/host/rk_sdmmc.h b/drivers/mmc/host/rk_sdmmc.h deleted file mode 100755 index cad989246002..000000000000 --- a/drivers/mmc/host/rk_sdmmc.h +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Synopsys DesignWare Multimedia Card Interface driver - * (Based on NXP driver for lpc 31xx) - * - * Copyright (C) 2009 NXP Semiconductors - * Copyright (C) 2009, 2010 Imagination Technologies Ltd. - * - * Copyright (C) 2014 Fuzhou Rockchip Electronics Co.Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef _DW_MMC_H_ -#define _DW_MMC_H_ -#include "rk_sdmmc_dbg.h" - -#define DW_MMC_240A 0x240a -#define DW_MMC_270A 0x270a - -#define SDMMC_CTRL 0x000 -#define SDMMC_PWREN 0x004 -#define SDMMC_CLKDIV 0x008 -#define SDMMC_CLKSRC 0x00c -#define SDMMC_CLKENA 0x010 -#define SDMMC_TMOUT 0x014 -#define SDMMC_CTYPE 0x018 -#define SDMMC_BLKSIZ 0x01c -#define SDMMC_BYTCNT 0x020 -#define SDMMC_INTMASK 0x024 -#define SDMMC_CMDARG 0x028 -#define SDMMC_CMD 0x02c -#define SDMMC_RESP0 0x030 -#define SDMMC_RESP1 0x034 -#define SDMMC_RESP2 0x038 -#define SDMMC_RESP3 0x03c -#define SDMMC_MINTSTS 0x040 -#define SDMMC_RINTSTS 0x044 -#define SDMMC_STATUS 0x048 -#define SDMMC_FIFOTH 0x04c -#define SDMMC_CDETECT 0x050 -#define SDMMC_WRTPRT 0x054 -#define SDMMC_GPIO 0x058 -#define SDMMC_TCBCNT 0x05c -#define SDMMC_TBBCNT 0x060 -#define SDMMC_DEBNCE 0x064 -#define SDMMC_USRID 0x068 -#define SDMMC_VERID 0x06c -#define SDMMC_HCON 0x070 -#define SDMMC_UHS_REG 0x074 -#define SDMMC_RST_N 0x078 -#define SDMMC_BMOD 0x080 -#define SDMMC_PLDMND 0x084 -#define SDMMC_DBADDR 0x088 -#define SDMMC_IDSTS 0x08c -#define SDMMC_IDINTEN 0x090 -#define SDMMC_DSCADDR 0x094 -#define SDMMC_BUFADDR 0x098 -#define SDMMC_CDTHRCTL 0x100 -#define SDMMC_DATA(x) (x) - - -static const u8 tuning_blk_pattern_4bit[] = { - 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, - 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, - 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, - 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, - 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, - 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, - 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, - 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, -}; - -static const u8 tuning_blk_pattern_8bit[] = { - 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, - 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, - 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, - 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, - 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, - 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, - 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, - 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, - 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, - 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, - 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, - 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, - 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, - 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, - 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, -}; - -/* - * Data offset is difference according to Version - * Lower than 2.40a : data register offest is 0x100 - */ -#define DATA_OFFSET 0x100 -#define DATA_240A_OFFSET 0x200 - -/* shift bit field */ -#define _SBF(f, v) ((v) << (f)) - - -struct sdmmc_reg { -u32 addr; -char *name; -}; - -static const struct sdmmc_reg dw_mci_regs[] = { -{ 0x0000, "CTRL" }, -{ 0x0004, "PWREN" }, -{ 0x0008, "CLKDIV" }, -{ 0x000C, "CLKSRC" }, -{ 0x0010, "CLKENA" }, -{ 0x0014, "TMOUT" }, -{ 0x0018, "CTYPE" }, -{ 0x001C, "BLKSIZ" }, -{ 0x0020, "BYTCNT" }, -{ 0x0024, "INTMASK" }, -{ 0x0028, "CMDARG" }, -{ 0x002C, "CMD" }, -{ 0x0030, "RESP0" }, -{ 0x0034, "RESP1" }, -{ 0x0038, "RESP2" }, -{ 0x003C, "RESP3" }, -{ 0x0040, "MINSTS" }, -{ 0x0044, "RINTSTS" }, -{ 0x0048, "STATUS" }, -{ 0x004C, "FIFOTH" }, -{ 0x0050, "CDETECT" }, -{ 0x0054, "WRTPRT" }, -{ 0x0058, "GPIO" }, -{ 0x005C, "TCBCNT" }, -{ 0x0060, "TBBCNT" }, -{ 0x0064, "DEBNCE" }, -{ 0x0068, "USRID" }, -{ 0x006C, "VERID" }, -{ 0x0070, "HCON" }, -{ 0x0074, "UHS_REG" }, -{ 0x0078, "RST_n" }, -{ 0x0080, "BMOD" }, -{ 0x0084, "PLDMND" }, -{ 0x0088, "DBADDR" }, -{ 0x008C, "IDSTS" }, -{ 0x0090, "IDINTEN" }, -{ 0x0094, "DSCADDR" }, -{ 0x0098, "BUFADDR" }, -{ 0x0100, "CARDTHRCTL" }, -{ 0x0104, "BackEndPwr" }, -{ 0, 0 } -}; - - -/* Control register defines */ -#define SDMMC_CTRL_USE_IDMAC BIT(25) -#define SDMMC_CTRL_CEATA_INT_EN BIT(11) -#define SDMMC_CTRL_SEND_AS_CCSD BIT(10) -#define SDMMC_CTRL_SEND_CCSD BIT(9) -#define SDMMC_CTRL_ABRT_READ_DATA BIT(8) -#define SDMMC_CTRL_SEND_IRQ_RESP BIT(7) -#define SDMMC_CTRL_READ_WAIT BIT(6) -#define SDMMC_CTRL_DMA_ENABLE BIT(5) -#define SDMMC_CTRL_INT_ENABLE BIT(4) -#define SDMMC_CTRL_DMA_RESET BIT(2) -#define SDMMC_CTRL_FIFO_RESET BIT(1) -#define SDMMC_CTRL_RESET BIT(0) -/* Clock Enable register defines */ -#define SDMMC_CLKEN_LOW_PWR BIT(16) -#define SDMMC_CLKEN_ENABLE BIT(0) -/* time-out register defines */ -#define SDMMC_TMOUT_DATA(n) _SBF(8, (n)) -#define SDMMC_TMOUT_DATA_MSK 0xFFFFFF00 -#define SDMMC_TMOUT_RESP(n) ((n) & 0xFF) -#define SDMMC_TMOUT_RESP_MSK 0xFF -/* card-type register defines */ -#define SDMMC_CTYPE_8BIT BIT(16) -#define SDMMC_CTYPE_4BIT BIT(0) -#define SDMMC_CTYPE_1BIT 0 -/* Interrupt status & mask register defines */ -#define SDMMC_INT_SDIO(n) BIT(16 + (n)) -#define SDMMC_INT_EBE BIT(15) -#define SDMMC_INT_ACD BIT(14) -#define SDMMC_INT_SBE BIT(13) -#define SDMMC_INT_HLE BIT(12) -#define SDMMC_INT_FRUN BIT(11) -#define SDMMC_INT_HTO BIT(10) -#define SDMMC_INT_VSI SDMMC_INT_HTO -#define SDMMC_INT_DRTO BIT(9) -#define SDMMC_INT_RTO BIT(8) -#define SDMMC_INT_DCRC BIT(7) -#define SDMMC_INT_RCRC BIT(6) -#define SDMMC_INT_RXDR BIT(5) -#define SDMMC_INT_TXDR BIT(4) -#define SDMMC_INT_DATA_OVER BIT(3) -#define SDMMC_INT_CMD_DONE BIT(2) -#define SDMMC_INT_RESP_ERR BIT(1) -#define SDMMC_INT_CD BIT(0) -#define SDMMC_INT_ERROR 0xbfc2 -/* Command register defines */ -#define SDMMC_CMD_START BIT(31) -#define SDMMC_CMD_USE_HOLD_REG BIT(29) -#define SDMMC_CMD_VOLT_SWITCH BIT(28) -#define SDMMC_CMD_BOOT_MODE BIT(27) -#define SDMMC_CMD_DISABLE_BOOT BIT(26) -#define SDMMC_CMD_EXPECT_BOOT_ACK BIT(25) -#define SDMMC_CMD_ENABLE_BOOT BIT(24) -#define SDMMC_CMD_CCS_EXP BIT(23) -#define SDMMC_CMD_CEATA_RD BIT(22) -#define SDMMC_CMD_UPD_CLK BIT(21) -#define SDMMC_CMD_INIT BIT(15) -#define SDMMC_CMD_STOP BIT(14) -#define SDMMC_CMD_PRV_DAT_WAIT BIT(13) -#define SDMMC_CMD_SEND_STOP BIT(12) -#define SDMMC_CMD_STRM_MODE BIT(11) -#define SDMMC_CMD_DAT_WR BIT(10) -#define SDMMC_CMD_DAT_EXP BIT(9) -#define SDMMC_CMD_RESP_CRC BIT(8) -#define SDMMC_CMD_RESP_LONG BIT(7) -#define SDMMC_CMD_RESP_EXP BIT(6) -#define SDMMC_CMD_INDX(n) ((n) & 0x1F) -/* Status register defines */ -#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF) -#define SDMMC_STAUTS_MC_BUSY BIT(10) -#define SDMMC_STAUTS_DATA_BUSY BIT(9) -#define SDMMC_CMD_FSM_MASK (0x0F << 4) -#define SDMMC_CMD_FSM_IDLE (0x00) -#define SDMMC_STAUTS_FIFO_FULL BIT(3) -#define SDMMC_STAUTS_FIFO_EMPTY BIT(2) - -/* Control SDMMC_UHS_REG defines (base+ 0x74)*/ -#define SDMMC_UHS_DDR_MODE BIT(16) -#define SDMMC_UHS_VOLT_REG_18 BIT(0) - -/* FIFOTH register defines */ -#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \ - ((r) & 0xFFF) << 16 | \ - ((t) & 0xFFF)) -/* Internal DMAC interrupt defines */ -#define SDMMC_IDMAC_INT_AI BIT(9) -#define SDMMC_IDMAC_INT_NI BIT(8) -#define SDMMC_IDMAC_INT_CES BIT(5) -#define SDMMC_IDMAC_INT_DU BIT(4) -#define SDMMC_IDMAC_INT_FBE BIT(2) -#define SDMMC_IDMAC_INT_RI BIT(1) -#define SDMMC_IDMAC_INT_TI BIT(0) -/* Internal DMAC bus mode bits */ -#define SDMMC_IDMAC_ENABLE BIT(7) -#define SDMMC_IDMAC_FB BIT(1) -#define SDMMC_IDMAC_SWRESET BIT(0) -/* Version ID register define */ -#define SDMMC_GET_VERID(x) ((x) & 0xFFFF) -/* Card read threshold */ -#define SDMMC_SET_RD_THLD(v, x) (((v) & 0xFFF) << 16 | (x)) - -/* Register access macros */ -#define mci_readl(dev, reg) \ - __raw_readl((dev)->regs + SDMMC_##reg) -#define mci_writel(dev, reg, value) \ - __raw_writel((value), (dev)->regs + SDMMC_##reg) -#define mci_readreg(dev, addr) \ - __raw_readl((dev)->regs + addr) -#define mci_writereg(dev, addr, value) \ - __raw_writel((value), (dev)->regs + addr) - - -/* 16-bit FIFO access macros */ -#define mci_readw(dev, reg) \ - __raw_readw((dev)->regs + SDMMC_##reg) -#define mci_writew(dev, reg, value) \ - __raw_writew((value), (dev)->regs + SDMMC_##reg) - -/* 64-bit FIFO access macros */ -#ifdef readq -#define mci_readq(dev, reg) \ - __raw_readq((dev)->regs + SDMMC_##reg) -#define mci_writeq(dev, reg, value) \ - __raw_writeq((value), (dev)->regs + SDMMC_##reg) -#else -/* - * Dummy readq implementation for architectures that don't define it. - * - * We would assume that none of these architectures would configure - * the IP block with a 64bit FIFO width, so this code will never be - * executed on those machines. Defining these macros here keeps the - * rest of the code free from ifdefs. - */ -#define mci_readq(dev, reg) \ - (*(u64 __force *)((dev)->regs + SDMMC_##reg)) -#define mci_writeq(dev, reg, value) \ - (*(u64 __force *)((dev)->regs + SDMMC_##reg) = (value)) -#endif -#ifdef CONFIG_PM -extern int dw_mci_suspend(struct dw_mci *host); -extern int dw_mci_resume(struct dw_mci *host); -#endif -static const struct dw_mci_rst_ops dw_mci_pdrst_ops; - -/** - * struct dw_mci_slot - MMC slot state - * @mmc: The mmc_host representing this slot. - * @host: The MMC controller this slot is using. - * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX) - * @wp_gpio: If gpio_is_valid() we'll use this to read write protect. - * @ctype: Card type for this slot. - * @mrq: mmc_request currently being processed or waiting to be - * processed, or NULL when the slot is idle. - * @queue_node: List node for placing this node in the @queue list of - * &struct dw_mci. - * @clock: Clock rate configured by set_ios(). Protected by host->lock. - * @__clk_old: The last updated clock with reflecting clock divider. - * Keeping track of this helps us to avoid spamming the console - * with CONFIG_MMC_CLKGATE. - * @flags: Random state bits associated with the slot. - * @id: Number of this slot. - * @last_detect_state: Most recently observed card detect state. - */ -struct dw_mci_slot { -struct mmc_host *mmc; -struct dw_mci *host; -int quirks; -int wp_gpio; -int cd_gpio; -int pwr_en_gpio; -u32 ctype; -u32 pre_ctype; - -struct mmc_request *mrq; -struct list_head queue_node; - -unsigned int clock; -unsigned int __clk_old; - -unsigned long flags; -#define DW_MMC_CARD_PRESENT 0 -#define DW_MMC_CARD_NEED_INIT 1 -int id; -int last_detect_state; -}; - -struct dw_mci_tuning_data { - const u8 *blk_pattern; - unsigned int blksz; -}; - -/** - * dw_mci driver data - dw-mshc implementation specific driver data. - * @caps: mmc subsystem specified capabilities of the controller(s). - * @hold_reg_flag: Fixed the value of HOLG_REG - * @init: early implementation specific initialization. - * @setup_clock: implementation specific clock configuration. - * @prepare_command: handle CMD register extensions. - * @set_ios: handle bus specific extensions. - * @parse_dt: parse implementation specific device tree properties. - * - * Provide controller implementation specific extensions. The usage of this - * data structure is fully optional and usage of each member in this structure - * is optional as well. - */ - -struct dw_mci_drv_data { - unsigned long *caps; - unsigned int *hold_reg_flag; - - int (*init)(struct dw_mci *host); - int (*setup_clock)(struct dw_mci *host); - void (*prepare_command)(struct dw_mci *host, u32 *cmdr); - void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); - int (*parse_dt)(struct dw_mci *host); - int (*execute_tuning)(struct dw_mci_slot *slot, - u32 opcode, - struct dw_mci_tuning_data - *tuning_data); -}; - -/* Variations in Rockchip specific dw-mshc controller */ -enum dw_mci_rockchip_type { -DW_MCI_TYPE_RK3188, -DW_MCI_TYPE_RK3288, -DW_MCI_TYPE_RK3036, -DW_MCI_TYPE_RK312X, -DW_MCI_TYPE_RK3368, -DW_MCI_TYPE_RK3228, -}; - -#endif /* _DW_MMC_H_ */ From d02681b53a9c8a4775473917d4d9cfb06c4959c4 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 17:59:13 +0800 Subject: [PATCH 32/51] iio: adc: rockchip_saradc: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: I21009e40bbd55b24ad0960098eb3d147f6b40c74 --- drivers/iio/adc/rockchip_saradc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 7bd7ba55007e..69dedaa6fa6f 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Rockchip Successive Approximation Register (SAR) A/D Converter - * Copyright (C) 2014 ROCKCHIP, Inc. + * Copyright (C) 2014 Rockchip Electronics Co., Ltd. */ #include From ceaf6706f0c99aa92eadac48e3183c4bb27de8ef Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 18:01:30 +0800 Subject: [PATCH 33/51] iio: light: ucs12cm0: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: I795db4c3bceea87036f0ca7ac8185d301e65dd73 --- drivers/iio/light/ucs12cm0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/light/ucs12cm0.c b/drivers/iio/light/ucs12cm0.c index b32dece65d4e..133e8cfb6bba 100644 --- a/drivers/iio/light/ucs12cm0.c +++ b/drivers/iio/light/ucs12cm0.c @@ -2,7 +2,7 @@ /* * UCS12CM0 illuminance and correlated color temperature sensor * - * Copyright (C) 2022-2025 ROCKCHIP. + * Copyright (C) 2022-2025 Rockchip Electronics Co., Ltd. * Author: Jason Zhang * * IIO driver for UCS12CM0 (7-bit I2C slave address 0x38) From 050d99f695755f841dc10b17f94fd068eb3b24ed Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 18:03:15 +0800 Subject: [PATCH 34/51] input: touchscreen: Fix typos in Rockchip copyright notices Signed-off-by: Tao Huang Change-Id: Ief54e322b8cd2f428810de46a3bda31588f23520 --- drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h | 2 +- .../touchscreen/rochkchip_gslX680_8inch_800x1280_tg806_10.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h b/drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h index 89b74fe3e23c..56df4062587e 100644 --- a/drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h +++ b/drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h @@ -1,7 +1,7 @@ /* * drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h * - * Copyright (c) 2017 rockchip + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. * * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/input/touchscreen/rochkchip_gslX680_8inch_800x1280_tg806_10.h b/drivers/input/touchscreen/rochkchip_gslX680_8inch_800x1280_tg806_10.h index a8ae94e29111..7d424c1e1c30 100644 --- a/drivers/input/touchscreen/rochkchip_gslX680_8inch_800x1280_tg806_10.h +++ b/drivers/input/touchscreen/rochkchip_gslX680_8inch_800x1280_tg806_10.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. * * Author: Wangqiang Guo */ From 14359418a47b8c8f6ec51b36d1c9e902b5314c11 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 18:04:42 +0800 Subject: [PATCH 35/51] mailbox: rockchip: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: I1850434be596a5f78ff01f985d5677ee606f8882 --- drivers/mailbox/rockchip-mailbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mailbox/rockchip-mailbox.c b/drivers/mailbox/rockchip-mailbox.c index 783d0fd7563a..4dd6963d82a5 100644 --- a/drivers/mailbox/rockchip-mailbox.c +++ b/drivers/mailbox/rockchip-mailbox.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2024, Rockchip Electronics Co., Ltd + * Copyright (c) 2024, Rockchip Electronics Co., Ltd. */ #include From ee9bc19eb8b2d8fb1dfd3cecf4d8e9e4dbf006cc Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 18:05:05 +0800 Subject: [PATCH 36/51] mailbox: rockchip-mbox-demo: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: Ie778a88d9246e7d81a830ec2a55cd13de7e490e3 --- drivers/mailbox/rockchip-mbox-demo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mailbox/rockchip-mbox-demo.c b/drivers/mailbox/rockchip-mbox-demo.c index 17a313b7e0ab..b91c55e1ac87 100644 --- a/drivers/mailbox/rockchip-mbox-demo.c +++ b/drivers/mailbox/rockchip-mbox-demo.c @@ -2,7 +2,7 @@ /* * Rockchip MBOX Demo. * - * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. * Author: Jiahang Zheng */ From 7876043db45f7f49e2cd881d0cb809d87d1a3cb6 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 18:06:01 +0800 Subject: [PATCH 37/51] media: videobuf2-cma-sg: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: I492d3d9503e2de8cc0f9b23a388d94ecd135cbbe --- drivers/media/common/videobuf2/videobuf2-cma-sg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/common/videobuf2/videobuf2-cma-sg.c b/drivers/media/common/videobuf2/videobuf2-cma-sg.c index 84b447100db0..b2f8340ddb7e 100644 --- a/drivers/media/common/videobuf2/videobuf2-cma-sg.c +++ b/drivers/media/common/videobuf2/videobuf2-cma-sg.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2022 Rockchip Electronics Co., Ltd + * Copyright (C) 2022 Rockchip Electronics Co., Ltd. * Based on videobuf2-dma-sg.c */ From 3c6462106f12cd91a1d4c9322cb55796de01eb13 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 20 Dec 2024 18:07:55 +0800 Subject: [PATCH 38/51] mmc: rk_sdmmc: Fix typo in Rockchip copyright notice Signed-off-by: Tao Huang Change-Id: Icd7563b320deba47960ce571e8780c17a323e5b8 --- drivers/mmc/host/rk_sdmmc_ops.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/rk_sdmmc_ops.h b/drivers/mmc/host/rk_sdmmc_ops.h index 81890ab6a94e..4f68c1a35951 100644 --- a/drivers/mmc/host/rk_sdmmc_ops.h +++ b/drivers/mmc/host/rk_sdmmc_ops.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2021 Rockchip Inc. + * Copyright (C) 2021 Rockchip Electronics Co., Ltd. */ #ifndef _RK_SDMMC_OPS_H_ From e31fbef6dde101257d495f879861c5b4ae1a1201 Mon Sep 17 00:00:00 2001 From: Jake Wu Date: Fri, 20 Dec 2024 15:51:26 +0800 Subject: [PATCH 39/51] arm64: dts: rockchip: px30-evb-ddr3-v10: fix sw1/2 for rk809 Type: Fix Redmine ID: #525434 Associated modifications: N/A Test: self-test Signed-off-by: Jake Wu Change-Id: I4271ad161c1a80250629ad133704bfe837cf0150 --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi index c733ca4b32c8..8ef7171c11b5 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi @@ -483,13 +483,13 @@ }; }; - vcc5v0_host: SWITCH_REG2 { + vcc5v0_host: SWITCH_REG1 { regulator-always-on; regulator-boot-on; regulator-name = "vcc5v0_host"; }; - vcc3v3_lcd: SWITCH_REG1 { + vcc3v3_lcd: SWITCH_REG2 { regulator-boot-on; regulator-name = "vcc3v3_lcd"; }; From 9764ff43485be1684be248fccbf45774abc7f13e Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Mon, 23 Dec 2024 18:26:40 +0800 Subject: [PATCH 40/51] mtd: spi-nor: esmt: Support en25qx64a Change-Id: Ic52e1748c80aed6feea17aa5dbeab262c7b55f0a Signed-off-by: Jon Lin --- drivers/mtd/spi-nor/esmt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/spi-nor/esmt.c b/drivers/mtd/spi-nor/esmt.c index b91b4ba801e3..5d92b77756f2 100644 --- a/drivers/mtd/spi-nor/esmt.c +++ b/drivers/mtd/spi-nor/esmt.c @@ -32,6 +32,9 @@ static const struct flash_info esmt_nor_parts[] = { { "en25qx128a", INFO(0x1c7118, 0, 64 * 1024, 256) NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "en25qx64a", INFO(0x1c7117, 0, 64 * 1024, 128) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | + SPI_NOR_QUAD_READ) }, }; const struct spi_nor_manufacturer spi_nor_esmt = { From 999ff49607f78208977e299763350933eaadbada Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Mon, 23 Dec 2024 18:27:40 +0800 Subject: [PATCH 41/51] mtd: spi-nor: puya: Support PY25Q256LC Change-Id: I99a39fc0cf86477aa97e4eb555856d8f6a0e9e77 Signed-off-by: Jon Lin --- drivers/mtd/spi-nor/puya.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/spi-nor/puya.c b/drivers/mtd/spi-nor/puya.c index b875702385cd..f1b913c136c8 100644 --- a/drivers/mtd/spi-nor/puya.c +++ b/drivers/mtd/spi-nor/puya.c @@ -26,6 +26,9 @@ static const struct flash_info puya_parts[] = { { "PY25Q128LA", INFO(0x856518, 0, 64 * 1024, 256) NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "PY25Q256LC", INFO(0x856519, 0, 64 * 1024, 512) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) + FIXUP_FLAGS(SPI_NOR_4B_OPCODES) }, }; const struct spi_nor_manufacturer spi_nor_puya = { From f5031143d9aa281c5315b79259a2f950d70cbdd0 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Mon, 23 Dec 2024 18:29:35 +0800 Subject: [PATCH 42/51] mtd: spi-nor: boya: Support BY25Q64ESSIG Change-Id: Ia670d98504a9bb1a2a9be5481b2186ecdabe1cce Signed-off-by: Jon Lin --- drivers/mtd/spi-nor/boya.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/spi-nor/boya.c b/drivers/mtd/spi-nor/boya.c index 669791e53a04..e94ef4e16bab 100644 --- a/drivers/mtd/spi-nor/boya.c +++ b/drivers/mtd/spi-nor/boya.c @@ -11,6 +11,8 @@ static const struct flash_info boya_parts[] = { { "BY25Q256FSEIG", INFO(0x684919, 0, 64 * 1024, 512) NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) FIXUP_FLAGS(SPI_NOR_4B_OPCODES) }, + { "BY25Q64ESSIG", INFO(0x684017, 0, 64 * 1024, 128) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, }; const struct spi_nor_manufacturer spi_nor_boya = { From ea444b6c9723fe563022b447af79c5c011167e26 Mon Sep 17 00:00:00 2001 From: Cody Xie Date: Fri, 13 Dec 2024 10:13:51 +0800 Subject: [PATCH 43/51] mfd: display-serdes: Fix out-of-bounds access issue Checked with kasan, the buggy stacktrace: BUG: KASAN: global-out-of-bounds in serdes_bridge_probe+0x2bc/0x568 Read of size 20 at addr ffffffc009a87240 by task swapper/0/1 CPU: 3 PID: 1 Comm: swapper/0 Tainted: G B 6.1.84 #7 Hardware name: Rockchip RK3576 VEHICLE EVB V20 MOS LINUX Board (DT) Call trace: dump_backtrace+0x11c/0x128 show_stack+0x1c/0x28 dump_stack_lvl+0x64/0x7c print_report+0x150/0x498 kasan_report+0x80/0xf0 kasan_check_range+0xe8/0x198 __asan_loadN+0x20/0x28 serdes_bridge_probe+0x2bc/0x568 platform_probe+0x90/0x108 really_probe+0x118/0x548 __driver_probe_device+0xc0/0x1f0 driver_probe_device+0x60/0x168 Fixes: 563845b4741e ("mfd: display-serdes: add serdes display driver support base on mfd arch") Change-Id: Ib0f6a674d75e0f9861163b0803f327963c3a85e5 Signed-off-by: Cody Xie --- drivers/mfd/display-serdes/serdes-bridge.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/display-serdes/serdes-bridge.c b/drivers/mfd/display-serdes/serdes-bridge.c index 49f8090429f3..9a6f9bf8aef4 100644 --- a/drivers/mfd/display-serdes/serdes-bridge.c +++ b/drivers/mfd/display-serdes/serdes-bridge.c @@ -7,6 +7,8 @@ * Author: luowei */ +#include + #include "core.h" static struct serdes_bridge *to_serdes_bridge(struct drm_bridge *bridge) @@ -24,7 +26,7 @@ static struct mipi_dsi_device *serdes_attach_dsi(struct serdes_bridge *serdes_br int ret; if (serdes->chip_data->name) - memcpy(&info.type, serdes->chip_data->name, ARRAY_SIZE(info.type)); + strscpy(info.type, serdes->chip_data->name, sizeof(info.type)); SERDES_DBG_MFD("%s: type=%s, name=%s\n", __func__, info.type, serdes->chip_data->name); From e1137ecfee63664f17a0c1490461d692775d6e24 Mon Sep 17 00:00:00 2001 From: Zhibin Huang Date: Tue, 17 Dec 2024 16:33:44 +0800 Subject: [PATCH 44/51] misc: rk628: dsi: add horizontal colorbar and BER pattern Type: Function Redmine ID: #N/A Associated modifications: N/A Test: N/A Signed-off-by: Zhibin Huang Change-Id: I79c7571100e2d547548e243e455b17e7609590fc --- drivers/misc/rk628/rk628_dsi.c | 44 ++++++++++++++++++++++++---------- drivers/misc/rk628/rk628_dsi.h | 2 ++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/drivers/misc/rk628/rk628_dsi.c b/drivers/misc/rk628/rk628_dsi.c index ed53a6724568..a2755565ca57 100644 --- a/drivers/misc/rk628/rk628_dsi.c +++ b/drivers/misc/rk628/rk628_dsi.c @@ -1292,7 +1292,11 @@ static void rk628_dsi_bridge_enable(struct rk628 *rk628, static int rk628_dsi_color_bar_show(struct seq_file *s, void *data) { - seq_puts(s, " Enable color bar:\n"); + seq_puts(s, " Enable horizontal color bar:\n"); + seq_puts(s, " example: echo 3 > /sys/kernel/debug/rk628/2-0050/dsi_color_bar\n"); + seq_puts(s, " Enable vertical color bar:\n"); + seq_puts(s, " example: echo 2 > /sys/kernel/debug/rk628/2-0050/dsi_color_bar\n"); + seq_puts(s, " Enable BER pattern (vertical only):\n"); seq_puts(s, " example: echo 1 > /sys/kernel/debug/rk628/2-0050/dsi_color_bar\n"); seq_puts(s, " Disable color bar:\n"); seq_puts(s, " example: echo 0 > /sys/kernel/debug/rk628/2-0050/dsi_color_bar\n"); @@ -1305,6 +1309,29 @@ static int rk628_dsi_color_bar_open(struct inode *inode, struct file *file) return single_open(file, rk628_dsi_color_bar_show, inode->i_private); } +static void rk628_dsi_color_bar(struct rk628 *rk628, struct rk628_dsi *dsi, u8 mode) +{ + switch (mode) { + case 3: // horizontal color bar + dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_ORIENTATION | VPG_MODE | VPG_EN, + VPG_ORIENTATION | 0 | VPG_EN); + break; + case 2: // vertical color bar + dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_ORIENTATION | VPG_MODE | VPG_EN, + 0 | 0 | VPG_EN); + break; + case 1: // BER pattern (vertical only) + dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_ORIENTATION | VPG_MODE | VPG_EN, + 0 | VPG_MODE | VPG_EN); + break; + default: // Disable color bar + dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_ORIENTATION | VPG_MODE | VPG_EN, + 0 | 0 | 0); + dsi_write(rk628, dsi, DSI_PWR_UP, RESET); + dsi_write(rk628, dsi, DSI_PWR_UP, POWER_UP); + } +} + static ssize_t rk628_dsi_color_bar_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { @@ -1316,19 +1343,10 @@ static ssize_t rk628_dsi_color_bar_write(struct file *file, const char __user *u if (kstrtou8_from_user(ubuf, len, 0, &mode)) return -EFAULT; - dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_EN, mode ? VPG_EN : 0); - if (!mode) { - dsi_write(rk628, dsi, DSI_PWR_UP, RESET); - dsi_write(rk628, dsi, DSI_PWR_UP, POWER_UP); - } + rk628_dsi_color_bar(rk628, dsi, mode); - if (dsi->slave) { - dsi_update_bits(rk628, dsi1, DSI_VID_MODE_CFG, VPG_EN, mode ? VPG_EN : 0); - if (!mode) { - dsi_write(rk628, dsi1, DSI_PWR_UP, RESET); - dsi_write(rk628, dsi1, DSI_PWR_UP, POWER_UP); - } - } + if (dsi->slave) + rk628_dsi_color_bar(rk628, dsi1, mode); return len; } diff --git a/drivers/misc/rk628/rk628_dsi.h b/drivers/misc/rk628/rk628_dsi.h index eb6dc7a578bd..668c5e5b9f62 100644 --- a/drivers/misc/rk628/rk628_dsi.h +++ b/drivers/misc/rk628/rk628_dsi.h @@ -43,6 +43,8 @@ #define DSI_MODE_CFG 0x0034 #define CMD_VIDEO_MODE(x) UPDATE(x, 0, 0) #define DSI_VID_MODE_CFG 0x0038 +#define VPG_ORIENTATION BIT(24) +#define VPG_MODE BIT(20) #define VPG_EN BIT(16) #define LP_CMD_EN BIT(15) #define FRAME_BTA_ACK_EN BIT(14) From fee15752e3222f759d20871fff1e66989c3f1e88 Mon Sep 17 00:00:00 2001 From: Jianlong Wang Date: Tue, 24 Dec 2024 14:25:25 +0800 Subject: [PATCH 45/51] arm64: dts: rockchip: rk3328-evb: enable analog_sound and hdmi_sound Change-Id: I3e844247e03767e55a7ff82608eafb75158c3d81 Signed-off-by: Jianlong Wang --- arch/arm64/boot/dts/rockchip/rk3328-evb.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts index 4e26244e112b..e2729fc3d483 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts @@ -138,6 +138,10 @@ }; }; +&analog_sound { + status = "okay"; +}; + &avsd { status = "okay"; }; @@ -232,6 +236,10 @@ status = "okay"; }; +&hdmi_sound { + status = "okay"; +}; + &hdmiphy { status = "okay"; }; From 1b3b835a3d58b7a8151a6cd48ad9bc7646359560 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sat, 21 Dec 2024 17:10:15 +0800 Subject: [PATCH 46/51] ASoC: rockchip: sai: Use SNDRV_PCM_RATE_CONTINUOUS Use SNDRV_PCM_RATE_CONTINUOUS to support continuous range sample rate, which can support any rate in range. e.g. 48048, 31000, 768000 SNDRV_PCM_RATE_CONTINUOUS means the hardware supports all rates in a specific interval. Sample rates are only restricted by the capabilities of the clock driver, so use SNDRV_PCM_RATE_CONTINUOUS instead of SNDRV_PCM_RATE_8000_384000. Signed-off-by: Sugar Zhang Change-Id: Ibff0ad918599a18ef29782ff379095996627d7be --- sound/soc/rockchip/rockchip_sai.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c index efa377fe23af..077a66e8c761 100644 --- a/sound/soc/rockchip/rockchip_sai.c +++ b/sound/soc/rockchip/rockchip_sai.c @@ -1226,7 +1226,7 @@ static int rockchip_sai_init_dai(struct rk_sai_dev *sai, struct resource *res, dai->playback.stream_name = "Playback"; dai->playback.channels_min = 1; dai->playback.channels_max = 512; - dai->playback.rates = SNDRV_PCM_RATE_8000_384000; + dai->playback.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->playback.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -1242,7 +1242,7 @@ static int rockchip_sai_init_dai(struct rk_sai_dev *sai, struct resource *res, dai->capture.stream_name = "Capture"; dai->capture.channels_min = 1; dai->capture.channels_max = 512; - dai->capture.rates = SNDRV_PCM_RATE_8000_384000; + dai->capture.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->capture.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | From f13609833752c581c46ef77f9442d24eec354847 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Mon, 23 Dec 2024 09:58:42 +0800 Subject: [PATCH 47/51] ASoC: dummy-codec: Use SNDRV_PCM_RATE_CONTINUOUS Use SNDRV_PCM_RATE_CONTINUOUS to support continuous range sample rate, which can support any rate in range. e.g. 48048, 31000, 768000 SNDRV_PCM_RATE_CONTINUOUS means the hardware supports all rates in a specific interval. Sample rates are only restricted by the capabilities of the clock driver, so use SNDRV_PCM_RATE_CONTINUOUS instead of SNDRV_PCM_RATE_8000_384000. Signed-off-by: Sugar Zhang Change-Id: Iac49752b7919bc74ddcc89b53d34a6a5a96ea134 --- sound/soc/codecs/dummy-codec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/dummy-codec.c b/sound/soc/codecs/dummy-codec.c index 2cb3ae65d4f7..57b9e9937399 100644 --- a/sound/soc/codecs/dummy-codec.c +++ b/sound/soc/codecs/dummy-codec.c @@ -50,7 +50,7 @@ struct snd_soc_dai_driver dummy_dai = { .stream_name = "Dummy Playback", .channels_min = 1, .channels_max = 384, - .rates = SNDRV_PCM_RATE_8000_384000, + .rates = SNDRV_PCM_RATE_CONTINUOUS, .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | @@ -61,7 +61,7 @@ struct snd_soc_dai_driver dummy_dai = { .stream_name = "Dummy Capture", .channels_min = 1, .channels_max = 384, - .rates = SNDRV_PCM_RATE_8000_384000, + .rates = SNDRV_PCM_RATE_CONTINUOUS, .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | From 8ecc26a8a911eeab3ae7286c4a97d367b1e97c09 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Tue, 24 Dec 2024 11:41:59 +0800 Subject: [PATCH 48/51] ASoC: rockchip: i2s: Use SNDRV_PCM_RATE_CONTINUOUS Use SNDRV_PCM_RATE_CONTINUOUS to support continuous range sample rate, which can support any rate in range. e.g. 48048, 31000, 768000 SNDRV_PCM_RATE_CONTINUOUS means the hardware supports all rates in a specific interval. Sample rates are only restricted by the capabilities of the clock driver, so use SNDRV_PCM_RATE_CONTINUOUS instead of SNDRV_PCM_RATE_8000_384000. Signed-off-by: Sugar Zhang Change-Id: Ieeea4f9ae414f2fa6475fa5f6559162e15c688c9 --- sound/soc/rockchip/rockchip_i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 452f713ea7ad..c7ec42d74880 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -1054,7 +1054,7 @@ static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res, dai->playback.stream_name = "Playback"; dai->playback.channels_min = 2; dai->playback.channels_max = 8; - dai->playback.rates = SNDRV_PCM_RATE_8000_192000; + dai->playback.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->playback.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | @@ -1076,7 +1076,7 @@ static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res, dai->capture.stream_name = "Capture"; dai->capture.channels_min = 2; dai->capture.channels_max = 8; - dai->capture.rates = SNDRV_PCM_RATE_8000_192000; + dai->capture.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->capture.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | From 6c5d0a72ce690c1bdb27569f7b2d057ea26e8415 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Tue, 24 Dec 2024 11:42:39 +0800 Subject: [PATCH 49/51] ASoC: rockchip: i2s-tdm: Use SNDRV_PCM_RATE_CONTINUOUS Use SNDRV_PCM_RATE_CONTINUOUS to support continuous range sample rate, which can support any rate in range. e.g. 48048, 31000, 768000 SNDRV_PCM_RATE_CONTINUOUS means the hardware supports all rates in a specific interval. Sample rates are only restricted by the capabilities of the clock driver, so use SNDRV_PCM_RATE_CONTINUOUS instead of SNDRV_PCM_RATE_8000_384000. Signed-off-by: Sugar Zhang Change-Id: I4811ca8ea63ed72da8cd06e9e8bbd5f450683165 --- sound/soc/rockchip/rockchip_i2s_tdm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index 43aaab16c239..260195072ba3 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -2807,7 +2807,7 @@ static int rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm) dai->playback.stream_name = "Playback"; dai->playback.channels_min = 2; dai->playback.channels_max = 64; - dai->playback.rates = SNDRV_PCM_RATE_8000_192000; + dai->playback.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->playback.formats = formats; } @@ -2815,7 +2815,7 @@ static int rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm) dai->capture.stream_name = "Capture"; dai->capture.channels_min = 2; dai->capture.channels_max = 64; - dai->capture.rates = SNDRV_PCM_RATE_8000_192000; + dai->capture.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->capture.formats = formats; } From 3fd340d98872c25050945f8ed854a343d360be00 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Thu, 19 Dec 2024 10:45:01 +0800 Subject: [PATCH 50/51] video: rockchip: rga3: avoid multiple drop 'current->mm' Change-Id: I57fbb8800bf3af320a931b54b85a8a53094e6194 Signed-off-by: Yu Qiaowei --- drivers/video/rockchip/rga3/include/rga_job.h | 2 +- drivers/video/rockchip/rga3/rga_job.c | 95 +++++++++---------- 2 files changed, 45 insertions(+), 52 deletions(-) diff --git a/drivers/video/rockchip/rga3/include/rga_job.h b/drivers/video/rockchip/rga3/include/rga_job.h index bdd9ab9ed74a..28bf35bacc55 100644 --- a/drivers/video/rockchip/rga3/include/rga_job.h +++ b/drivers/video/rockchip/rga3/include/rga_job.h @@ -27,7 +27,7 @@ enum job_flags { void rga_job_scheduler_dump_info(struct rga_scheduler_t *scheduler); void rga_job_next(struct rga_scheduler_t *scheduler); struct rga_job *rga_job_done(struct rga_scheduler_t *scheduler); -struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request); +int rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request); int rga_job_mpi_commit(struct rga_req *rga_command_base, struct rga_request *request); int rga_job_assign(struct rga_job *job); diff --git a/drivers/video/rockchip/rga3/rga_job.c b/drivers/video/rockchip/rga3/rga_job.c index 2acbb9d9596d..fd254b587fde 100644 --- a/drivers/video/rockchip/rga3/rga_job.c +++ b/drivers/video/rockchip/rga3/rga_job.c @@ -403,7 +403,7 @@ static struct rga_scheduler_t *rga_job_schedule(struct rga_job *job) return scheduler; } -struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request) +int rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request) { int ret; struct rga_job *job = NULL; @@ -412,7 +412,7 @@ struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_requ job = rga_job_alloc(rga_command_base); if (!job) { rga_err("failed to alloc rga job!\n"); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } job->use_batch_mode = request->use_batch_mode; @@ -458,7 +458,7 @@ struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_requ rga_power_disable(scheduler); - return job; + return 0; err_unmap_job_info: rga_mm_unmap_job_info(job); @@ -472,9 +472,9 @@ err_free_cmd_buf: err_free_job: ret = job->ret; - rga_request_release_signal(scheduler, job); + rga_job_free(job); - return ERR_PTR(ret); + return ret; } static bool rga_is_need_current_mm(struct rga_req *req) @@ -908,20 +908,15 @@ static int rga_request_wait(struct rga_request *request) switch (left_time) { case 0: ret = rga_request_timeout_query_state(request); - goto err_request_abort; + break; case -ERESTARTSYS: ret = -ERESTARTSYS; - goto err_request_abort; + break; default: ret = request->ret; break; } - return ret; - -err_request_abort: - rga_request_release_abort(request, ret); - return ret; } @@ -929,7 +924,6 @@ int rga_request_commit(struct rga_request *request) { int ret; int i = 0; - struct rga_job *job; if (DEBUGGER_EN(MSG)) rga_req_log(request, "commit process: %s\n", request->session->pname); @@ -942,12 +936,11 @@ int rga_request_commit(struct rga_request *request) rga_dump_req(request, req); } - job = rga_job_commit(req, request); - if (IS_ERR(job)) { + ret = rga_job_commit(req, request); + if (ret < 0) { rga_req_err(request, "task[%d] job_commit failed.\n", i); - rga_request_release_abort(request, PTR_ERR(job)); - return PTR_ERR(job); + return ret; } } @@ -1220,9 +1213,6 @@ int rga_request_submit(struct rga_request *request) int ret = 0; unsigned long flags; struct dma_fence *release_fence; - struct mm_struct *current_mm; - - current_mm = rga_request_get_current_mm(request); spin_lock_irqsave(&request->lock, flags); @@ -1231,7 +1221,7 @@ int rga_request_submit(struct rga_request *request) rga_req_err(request, "can not re-config when request is running\n"); ret = -EFAULT; - goto err_put_current_mm; + goto err_abort_request; } if (request->task_list == NULL) { @@ -1239,7 +1229,7 @@ int rga_request_submit(struct rga_request *request) rga_req_err(request, "can not find task list\n"); ret = -EINVAL; - goto err_put_current_mm; + goto err_abort_request; } /* Reset */ @@ -1248,7 +1238,6 @@ int rga_request_submit(struct rga_request *request) request->finished_task_count = 0; request->failed_task_count = 0; request->ret = 0; - request->current_mm = current_mm; /* Unlock after ensuring that the current request will not be resubmitted. */ spin_unlock_irqrestore(&request->lock, flags); @@ -1258,8 +1247,10 @@ int rga_request_submit(struct rga_request *request) if (IS_ERR_OR_NULL(release_fence)) { rga_req_err(request, "Can not alloc release fence!\n"); ret = IS_ERR(release_fence) ? PTR_ERR(release_fence) : -EINVAL; - goto err_reset_request; + goto err_abort_request; } + + request->current_mm = rga_request_get_current_mm(request); request->release_fence = release_fence; if (request->acquire_fence_fd > 0) { @@ -1276,16 +1267,22 @@ int rga_request_submit(struct rga_request *request) } else { rga_req_err(request, "Failed to add callback with acquire fence fd[%d]!\n", request->acquire_fence_fd); - goto err_put_release_fence; + + rga_dma_fence_put(request->release_fence); + request->release_fence = NULL; + goto err_put_current_mm; } } + } else { + request->current_mm = rga_request_get_current_mm(request); + request->release_fence = NULL; } request_commit: ret = rga_request_commit(request); if (ret < 0) { rga_req_err(request, "request commit failed!\n"); - goto err_put_release_fence; + goto err_put_current_mm; } export_release_fence_fd: @@ -1293,8 +1290,7 @@ export_release_fence_fd: ret = rga_dma_fence_get_fd(request->release_fence); if (ret < 0) { rga_req_err(request, "Failed to alloc release fence fd!\n"); - rga_request_release_abort(request, ret); - return ret; + goto err_put_current_mm; } request->release_fence_fd = ret; @@ -1302,22 +1298,12 @@ export_release_fence_fd: return 0; -err_put_release_fence: - if (request->release_fence != NULL) { - rga_dma_fence_put(request->release_fence); - request->release_fence = NULL; - } - -err_reset_request: - spin_lock_irqsave(&request->lock, flags); - - request->current_mm = NULL; - request->is_running = false; - - spin_unlock_irqrestore(&request->lock, flags); - err_put_current_mm: - rga_request_put_current_mm(current_mm); + rga_request_put_current_mm(request->current_mm); + request->current_mm = NULL; + +err_abort_request: + rga_request_release_abort(request, ret); return ret; } @@ -1325,7 +1311,6 @@ err_put_current_mm: int rga_request_mpi_submit(struct rga_req *req, struct rga_request *request) { int ret = 0; - struct rga_job *job = NULL; unsigned long flags; struct rga_pending_request_manager *request_manager; @@ -1333,7 +1318,8 @@ int rga_request_mpi_submit(struct rga_req *req, struct rga_request *request) if (request->sync_mode == RGA_BLIT_ASYNC) { rga_req_err(request, "mpi unsupported async mode!\n"); - return -EINVAL; + ret = -EINVAL; + goto err_abort_request; } spin_lock_irqsave(&request->lock, flags); @@ -1341,13 +1327,15 @@ int rga_request_mpi_submit(struct rga_req *req, struct rga_request *request) if (request->is_running) { rga_req_err(request, "can not re-config when request is running"); spin_unlock_irqrestore(&request->lock, flags); - return -EFAULT; + ret = -EFAULT; + goto err_abort_request; } if (request->task_list == NULL) { rga_req_err(request, "can not find task list"); spin_unlock_irqrestore(&request->lock, flags); - return -EINVAL; + ret = -EINVAL; + goto err_abort_request; } /* Reset */ @@ -1367,17 +1355,22 @@ int rga_request_mpi_submit(struct rga_req *req, struct rga_request *request) rga_request_get(request); mutex_unlock(&request_manager->lock); - job = rga_job_commit(req, request); - if (IS_ERR_OR_NULL(job)) { + ret = rga_job_commit(req, request); + if (ret < 0) { rga_req_err(request, "failed to commit job!\n"); - return job ? PTR_ERR(job) : -EFAULT; + goto err_abort_request; } ret = rga_request_wait(request); if (ret < 0) - return ret; + goto err_abort_request; return 0; + +err_abort_request: + rga_request_release_abort(request, ret); + + return ret; } int rga_request_free(struct rga_request *request) From f8da7b4d7c308547ce6aebb25fee32164c7fedb1 Mon Sep 17 00:00:00 2001 From: Xu Xuehui Date: Wed, 25 Dec 2024 10:55:10 +0800 Subject: [PATCH 51/51] arm64: dts: rockchip: rk3588-vehicle-evb-v23: fix bt gpio config error Signed-off-by: Xu Xuehui Change-Id: Iaa44be32248c0bcac0d04971b5c5c3c9cfdec32e --- arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23.dts b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23.dts index ef72a61d3187..775cd3140ca2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23.dts @@ -308,7 +308,7 @@ pinctrl-0 = <&uart7m1_rtsn>, <&bt_reset_gpio>, <&bt_wake_gpio>, <&bt_irq_gpio>; pinctrl-1 = <&uart7_gpios>; BT,reset_gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; - BT,wake_gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + BT,wake_gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>; BT,wake_host_irq = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; status = "okay"; };