[PATCH 16/29][SRU][OEM-5.14] UBUNTU: SAUCE: IPU6 driver release for kernel 5.14 on 2021-11-01
You-Sheng Yang
vicamo.yang at canonical.com
Tue Dec 28 06:19:42 UTC 2021
From: Hao Yao <hao.yao at intel.com>
BugLink: https://bugs.launchpad.net/bugs/1955383
Add support for both Tiger Lake and Alder Lake platforms.
Add support for OV01A10 sensor.
Signed-off-by: Hao Yao <hao.yao at intel.com>
(backported from
https://github.com/intel/ipu6-drivers/commit/1f26f0c8cb13d14c22d9f7010b1b4774b89136a9
added CONFIG_VIDEO_OV01A10 to drivers/media/i2c/Kconfig)
Signed-off-by: You-Sheng Yang <vicamo.yang at canonical.com>
---
drivers/media/i2c/Kconfig | 14 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/hm11b1.c | 17 +-
drivers/media/i2c/ov01a10.c | 934 ++++++++++++++++++
drivers/media/i2c/ov01a1s.c | 37 +-
drivers/media/i2c/power_ctrl_logic.c | 2 +-
drivers/media/pci/intel/Kconfig | 3 +-
drivers/media/pci/intel/ipu-buttress.c | 59 +-
drivers/media/pci/intel/ipu-buttress.h | 1 -
.../media/pci/intel/ipu-isys-csi2-be-soc.c | 18 +-
drivers/media/pci/intel/ipu-isys-csi2-be.c | 325 ++++++
drivers/media/pci/intel/ipu-isys-csi2.c | 40 +-
drivers/media/pci/intel/ipu-isys-subdev.c | 95 +-
drivers/media/pci/intel/ipu-isys-subdev.h | 23 +-
drivers/media/pci/intel/ipu-isys-tpg.c | 311 ++++++
drivers/media/pci/intel/ipu-isys-tpg.h | 99 ++
drivers/media/pci/intel/ipu-isys.c | 32 +-
drivers/media/pci/intel/ipu-isys.h | 1 -
drivers/media/pci/intel/ipu-mmu.c | 4 +-
drivers/media/pci/intel/ipu-psys-compat32.c | 1 -
drivers/media/pci/intel/ipu-psys.c | 16 +-
drivers/media/pci/intel/ipu-psys.h | 5 +-
drivers/media/pci/intel/ipu.c | 6 +-
drivers/media/pci/intel/ipu.h | 3 +-
drivers/media/pci/intel/ipu6/ipu-resources.c | 32 +-
.../media/pci/intel/ipu6/ipu6-fw-resources.c | 23 +-
drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c | 6 +-
drivers/media/pci/intel/ipu6/ipu6-isys-phy.c | 36 +-
drivers/media/pci/intel/ipu6/ipu6-ppg.c | 11 +-
drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c | 6 +-
drivers/media/pci/intel/ipu6/ipu6-psys.c | 32 +-
.../pci/intel/ipu6/ipu6ep-fw-resources.c | 10 +-
32 files changed, 1910 insertions(+), 293 deletions(-)
create mode 100644 drivers/media/i2c/ov01a10.c
create mode 100644 drivers/media/pci/intel/ipu-isys-csi2-be.c
create mode 100644 drivers/media/pci/intel/ipu-isys-tpg.c
create mode 100644 drivers/media/pci/intel/ipu-isys-tpg.h
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 3992c1b04d04..2baa70602722 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -1360,6 +1360,20 @@ config POWER_CTRL_LOGIC
To compile this driver as a module, choose M here: the
module will be called power_ctrl_logic.
+config VIDEO_OV01A10
+ tristate "OmniVision OV01A10 sensor support"
+ depends on VIDEO_V4L2 && I2C
+ depends on ACPI || COMPILE_TEST
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
+ select V4L2_FWNODE
+ help
+ This is a Video4Linux2 sensor driver for the OmniVision
+ OV01A10 camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ov01a10.
+
config VIDEO_OV01A1S
tristate "OmniVision OV01A1S sensor support"
depends on POWER_CTRL_LOGIC
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 4bfed5ed7cff..dae80fb28128 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -135,4 +135,5 @@ obj-$(CONFIG_SDR_MAX2175) += max2175.o
obj-$(CONFIG_VIDEO_HM11B1) += hm11b1.o
obj-$(CONFIG_VIDEO_OV01A1S) += ov01a1s.o
+obj-$(CONFIG_VIDEO_OV01A10) += ov01a10.o
obj-$(CONFIG_POWER_CTRL_LOGIC) += power_ctrl_logic.o
diff --git a/drivers/media/i2c/hm11b1.c b/drivers/media/i2c/hm11b1.c
index ecc74d2bc250..27d5acebb73c 100644
--- a/drivers/media/i2c/hm11b1.c
+++ b/drivers/media/i2c/hm11b1.c
@@ -7,6 +7,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
+#include <linux/version.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
@@ -847,7 +848,7 @@ static int __maybe_unused hm11b1_resume(struct device *dev)
}
static int hm11b1_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct hm11b1 *hm11b1 = to_hm11b1(sd);
@@ -862,7 +863,7 @@ static int hm11b1_set_format(struct v4l2_subdev *sd,
mutex_lock(&hm11b1->mutex);
hm11b1_update_pad_format(mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
+ *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
} else {
hm11b1->cur_mode = mode;
__v4l2_ctrl_s_ctrl(hm11b1->link_freq, mode->link_freq_index);
@@ -887,15 +888,15 @@ static int hm11b1_set_format(struct v4l2_subdev *sd,
}
static int hm11b1_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct hm11b1 *hm11b1 = to_hm11b1(sd);
mutex_lock(&hm11b1->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&hm11b1->sd, cfg,
- fmt->pad);
+ fmt->format = *v4l2_subdev_get_try_format(&hm11b1->sd,
+ sd_state, fmt->pad);
else
hm11b1_update_pad_format(hm11b1->cur_mode, &fmt->format);
@@ -905,7 +906,7 @@ static int hm11b1_get_format(struct v4l2_subdev *sd,
}
static int hm11b1_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index > 0)
@@ -917,7 +918,7 @@ static int hm11b1_enum_mbus_code(struct v4l2_subdev *sd,
}
static int hm11b1_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
if (fse->index >= ARRAY_SIZE(supported_modes))
@@ -940,7 +941,7 @@ static int hm11b1_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&hm11b1->mutex);
hm11b1_update_pad_format(&supported_modes[0],
- v4l2_subdev_get_try_format(sd, fh->pad, 0));
+ v4l2_subdev_get_try_format(sd, fh->state, 0));
mutex_unlock(&hm11b1->mutex);
return 0;
diff --git a/drivers/media/i2c/ov01a10.c b/drivers/media/i2c/ov01a10.c
new file mode 100644
index 000000000000..54968bbe1598
--- /dev/null
+++ b/drivers/media/i2c/ov01a10.c
@@ -0,0 +1,934 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2020-2021 Intel Corporation.
+
+#include <asm/unaligned.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/version.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+#include <linux/vsc.h>
+
+#define OV01A10_LINK_FREQ_400MHZ 400000000ULL
+#define OV01A10_SCLK 40000000LL
+#define OV01A10_MCLK 19200000
+#define OV01A10_DATA_LANES 1
+#define OV01A10_RGB_DEPTH 10
+
+#define OV01A10_REG_CHIP_ID 0x300a
+#define OV01A10_CHIP_ID 0x560141
+
+#define OV01A10_REG_MODE_SELECT 0x0100
+#define OV01A10_MODE_STANDBY 0x00
+#define OV01A10_MODE_STREAMING 0x01
+
+/* vertical-timings from sensor */
+#define OV01A10_REG_VTS 0x380e
+#define OV01A10_VTS_DEF 0x0380
+#define OV01A10_VTS_MIN 0x0380
+#define OV01A10_VTS_MAX 0xffff
+
+/* Exposure controls from sensor */
+#define OV01A10_REG_EXPOSURE 0x3501
+#define OV01A10_EXPOSURE_MIN 4
+#define OV01A10_EXPOSURE_MAX_MARGIN 8
+#define OV01A10_EXPOSURE_STEP 1
+
+/* Analog gain controls from sensor */
+#define OV01A10_REG_ANALOG_GAIN 0x3508
+#define OV01A10_ANAL_GAIN_MIN 0x100
+#define OV01A10_ANAL_GAIN_MAX 0xffff
+#define OV01A10_ANAL_GAIN_STEP 1
+
+/* Digital gain controls from sensor */
+#define OV01A10_REG_DIGILAL_GAIN_B 0x350A
+#define OV01A10_REG_DIGITAL_GAIN_GB 0x3510
+#define OV01A10_REG_DIGITAL_GAIN_GR 0x3513
+#define OV01A10_REG_DIGITAL_GAIN_R 0x3516
+#define OV01A10_DGTL_GAIN_MIN 0
+#define OV01A10_DGTL_GAIN_MAX 0x3ffff
+#define OV01A10_DGTL_GAIN_STEP 1
+#define OV01A10_DGTL_GAIN_DEFAULT 1024
+
+/* Test Pattern Control */
+#define OV01A10_REG_TEST_PATTERN 0x4503
+#define OV01A10_TEST_PATTERN_ENABLE BIT(7)
+#define OV01A10_TEST_PATTERN_BAR_SHIFT 0
+
+enum {
+ OV01A10_LINK_FREQ_400MHZ_INDEX,
+};
+
+struct ov01a10_reg {
+ u16 address;
+ u8 val;
+};
+
+struct ov01a10_reg_list {
+ u32 num_of_regs;
+ const struct ov01a10_reg *regs;
+};
+
+struct ov01a10_link_freq_config {
+ const struct ov01a10_reg_list reg_list;
+};
+
+struct ov01a10_mode {
+ /* Frame width in pixels */
+ u32 width;
+
+ /* Frame height in pixels */
+ u32 height;
+
+ /* Horizontal timining size */
+ u32 hts;
+
+ /* Default vertical timining size */
+ u32 vts_def;
+
+ /* Min vertical timining size */
+ u32 vts_min;
+
+ /* Link frequency needed for this resolution */
+ u32 link_freq_index;
+
+ /* Sensor register settings for this resolution */
+ const struct ov01a10_reg_list reg_list;
+};
+
+static const struct ov01a10_reg mipi_data_rate_720mbps[] = {
+};
+
+static const struct ov01a10_reg sensor_1280x800_setting[] = {
+ {0x0103, 0x01},
+ {0x0302, 0x00},
+ {0x0303, 0x06},
+ {0x0304, 0x01},
+ {0x0305, 0xe0},
+ {0x0306, 0x00},
+ {0x0308, 0x01},
+ {0x0309, 0x00},
+ {0x030c, 0x01},
+ {0x0322, 0x01},
+ {0x0323, 0x06},
+ {0x0324, 0x01},
+ {0x0325, 0x68},
+ {0x3002, 0xa1},
+ {0x301e, 0xf0},
+ {0x3022, 0x01},
+ {0x3501, 0x03},
+ {0x3502, 0x78},
+ {0x3504, 0x0c},
+ {0x3508, 0x01},
+ {0x3509, 0x00},
+ {0x3601, 0xc0},
+ {0x3603, 0x71},
+ {0x3610, 0x68},
+ {0x3611, 0x86},
+ {0x3640, 0x10},
+ {0x3641, 0x80},
+ {0x3642, 0xdc},
+ {0x3646, 0x55},
+ {0x3647, 0x57},
+ {0x364b, 0x00},
+ {0x3653, 0x10},
+ {0x3655, 0x00},
+ {0x3656, 0x00},
+ {0x365f, 0x0f},
+ {0x3661, 0x45},
+ {0x3662, 0x24},
+ {0x3663, 0x11},
+ {0x3664, 0x07},
+ {0x3709, 0x34},
+ {0x370b, 0x6f},
+ {0x3714, 0x22},
+ {0x371b, 0x27},
+ {0x371c, 0x67},
+ {0x371d, 0xa7},
+ {0x371e, 0xe7},
+ {0x3730, 0x81},
+ {0x3733, 0x10},
+ {0x3734, 0x40},
+ {0x3737, 0x04},
+ {0x3739, 0x1c},
+ {0x3767, 0x00},
+ {0x376c, 0x81},
+ {0x3772, 0x14},
+ {0x37c2, 0x04},
+ {0x37d8, 0x03},
+ {0x37d9, 0x0c},
+ {0x37e0, 0x00},
+ {0x37e1, 0x08},
+ {0x37e2, 0x10},
+ {0x37e3, 0x04},
+ {0x37e4, 0x04},
+ {0x37e5, 0x03},
+ {0x37e6, 0x04},
+ {0x3800, 0x00},
+ {0x3801, 0x00},
+ {0x3802, 0x00},
+ {0x3803, 0x00},
+ {0x3804, 0x05},
+ {0x3805, 0x0f},
+ {0x3806, 0x03},
+ {0x3807, 0x2f},
+ {0x3808, 0x05},
+ {0x3809, 0x00},
+ {0x380a, 0x03},
+ {0x380b, 0x20},
+ {0x380c, 0x02},
+ {0x380d, 0xe8},
+ {0x380e, 0x03},
+ {0x380f, 0x80},
+ {0x3810, 0x00},
+ {0x3811, 0x09},
+ {0x3812, 0x00},
+ {0x3813, 0x08},
+ {0x3814, 0x01},
+ {0x3815, 0x01},
+ {0x3816, 0x01},
+ {0x3817, 0x01},
+ {0x3820, 0xa8},
+ {0x3822, 0x13},
+ {0x3832, 0x28},
+ {0x3833, 0x10},
+ {0x3b00, 0x00},
+ {0x3c80, 0x00},
+ {0x3c88, 0x02},
+ {0x3c8c, 0x07},
+ {0x3c8d, 0x40},
+ {0x3cc7, 0x80},
+ {0x4000, 0xc3},
+ {0x4001, 0xe0},
+ {0x4003, 0x40},
+ {0x4008, 0x02},
+ {0x4009, 0x19},
+ {0x400a, 0x01},
+ {0x400b, 0x6c},
+ {0x4011, 0x00},
+ {0x4041, 0x00},
+ {0x4300, 0xff},
+ {0x4301, 0x00},
+ {0x4302, 0x0f},
+ {0x4503, 0x00},
+ {0x4601, 0x50},
+ {0x4800, 0x64},
+ {0x481f, 0x34},
+ {0x4825, 0x33},
+ {0x4837, 0x11},
+ {0x4881, 0x40},
+ {0x4883, 0x01},
+ {0x4890, 0x00},
+ {0x4901, 0x00},
+ {0x4902, 0x00},
+ {0x4b00, 0x2a},
+ {0x4b0d, 0x00},
+ {0x450a, 0x04},
+ {0x450b, 0x00},
+ {0x5000, 0x65},
+ {0x5200, 0x18},
+ {0x5004, 0x00},
+ {0x5080, 0x40},
+ {0x0305, 0xf4},
+ {0x0325, 0xc2},
+ {0x380c, 0x05},
+ {0x380d, 0xd0},
+};
+
+static const char * const ov01a10_test_pattern_menu[] = {
+ "Disabled",
+ "Color Bar",
+ "Top-Bottom Darker Color Bar",
+ "Right-Left Darker Color Bar",
+ "Color Bar type 4",
+};
+
+static const s64 link_freq_menu_items[] = {
+ OV01A10_LINK_FREQ_400MHZ,
+};
+
+static const struct ov01a10_link_freq_config link_freq_configs[] = {
+ [OV01A10_LINK_FREQ_400MHZ_INDEX] = {
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mipi_data_rate_720mbps),
+ .regs = mipi_data_rate_720mbps,
+ }
+ },
+};
+
+static const struct ov01a10_mode supported_modes[] = {
+ {
+ .width = 1280,
+ .height = 800,
+ .hts = 1488,
+ .vts_def = OV01A10_VTS_DEF,
+ .vts_min = OV01A10_VTS_MIN,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(sensor_1280x800_setting),
+ .regs = sensor_1280x800_setting,
+ },
+ .link_freq_index = OV01A10_LINK_FREQ_400MHZ_INDEX,
+ },
+};
+
+struct ov01a10 {
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+ struct v4l2_ctrl_handler ctrl_handler;
+
+ /* V4L2 Controls */
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *vblank;
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *exposure;
+
+ /* Current mode */
+ const struct ov01a10_mode *cur_mode;
+
+ /* To serialize asynchronus callbacks */
+ struct mutex mutex;
+
+ /* Streaming on/off */
+ bool streaming;
+};
+
+static inline struct ov01a10 *to_ov01a10(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct ov01a10, sd);
+}
+
+static int ov01a10_read_reg(struct ov01a10 *ov01a10, u16 reg, u16 len, u32 *val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ struct i2c_msg msgs[2];
+ u8 addr_buf[2];
+ u8 data_buf[4] = {0};
+ int ret = 0;
+
+ if (len > sizeof(data_buf))
+ return -EINVAL;
+
+ put_unaligned_be16(reg, addr_buf);
+ msgs[0].addr = client->addr;
+ msgs[0].flags = 0;
+ msgs[0].len = sizeof(addr_buf);
+ msgs[0].buf = addr_buf;
+ msgs[1].addr = client->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = len;
+ msgs[1].buf = &data_buf[sizeof(data_buf) - len];
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+
+ if (ret != ARRAY_SIZE(msgs))
+ return ret < 0 ? ret : -EIO;
+
+ *val = get_unaligned_be32(data_buf);
+
+ return 0;
+}
+
+static int ov01a10_write_reg(struct ov01a10 *ov01a10, u16 reg, u16 len, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ u8 buf[6];
+ int ret = 0;
+
+ if (len > 4)
+ return -EINVAL;
+
+ put_unaligned_be16(reg, buf);
+ put_unaligned_be32(val << 8 * (4 - len), buf + 2);
+
+ ret = i2c_master_send(client, buf, len + 2);
+ if (ret != len + 2)
+ return ret < 0 ? ret : -EIO;
+
+ return 0;
+}
+
+static int ov01a10_write_reg_list(struct ov01a10 *ov01a10,
+ const struct ov01a10_reg_list *r_list)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ unsigned int i;
+ int ret = 0;
+
+ for (i = 0; i < r_list->num_of_regs; i++) {
+ ret = ov01a10_write_reg(ov01a10, r_list->regs[i].address, 1,
+ r_list->regs[i].val);
+ if (ret) {
+ dev_err_ratelimited(&client->dev,
+ "write reg 0x%4.4x return err = %d",
+ r_list->regs[i].address, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int ov01a10_update_digital_gain(struct ov01a10 *ov01a10, u32 d_gain)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ u32 real = d_gain << 6;
+ int ret = 0;
+
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGILAL_GAIN_B, 3, real);
+ if (ret) {
+ dev_err(&client->dev, "failed to set OV01A10_REG_DIGITAL_GAIN_B");
+ return ret;
+ }
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_GB, 3, real);
+ if (ret) {
+ dev_err(&client->dev, "failed to set OV01A10_REG_DIGITAL_GAIN_GB");
+ return ret;
+ }
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_GR, 3, real);
+ if (ret) {
+ dev_err(&client->dev, "failed to set OV01A10_REG_DIGITAL_GAIN_GR");
+ return ret;
+ }
+
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_R, 3, real);
+ if (ret) {
+ dev_err(&client->dev, "failed to set OV01A10_REG_DIGITAL_GAIN_R");
+ return ret;
+ }
+ return ret;
+}
+
+static int ov01a10_test_pattern(struct ov01a10 *ov01a10, u32 pattern)
+{
+ if (pattern)
+ pattern = (pattern - 1) << OV01A10_TEST_PATTERN_BAR_SHIFT |
+ OV01A10_TEST_PATTERN_ENABLE;
+
+ return ov01a10_write_reg(ov01a10, OV01A10_REG_TEST_PATTERN, 1, pattern);
+}
+
+static int ov01a10_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct ov01a10 *ov01a10 = container_of(ctrl->handler,
+ struct ov01a10, ctrl_handler);
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ s64 exposure_max;
+ int ret = 0;
+
+ /* Propagate change of current control to all related controls */
+ if (ctrl->id == V4L2_CID_VBLANK) {
+ /* Update max exposure while meeting expected vblanking */
+ exposure_max = ov01a10->cur_mode->height + ctrl->val -
+ OV01A10_EXPOSURE_MAX_MARGIN;
+ __v4l2_ctrl_modify_range(ov01a10->exposure,
+ ov01a10->exposure->minimum,
+ exposure_max, ov01a10->exposure->step,
+ exposure_max);
+ }
+
+ /* V4L2 controls values will be applied only when power is already up */
+ if (!pm_runtime_get_if_in_use(&client->dev))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ANALOGUE_GAIN:
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_ANALOG_GAIN, 2,
+ ctrl->val);
+ break;
+
+ case V4L2_CID_DIGITAL_GAIN:
+ ret = ov01a10_update_digital_gain(ov01a10, ctrl->val);
+ break;
+
+ case V4L2_CID_EXPOSURE:
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_EXPOSURE, 2,
+ ctrl->val);
+ break;
+
+ case V4L2_CID_VBLANK:
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_VTS, 2,
+ ov01a10->cur_mode->height + ctrl->val);
+ break;
+
+ case V4L2_CID_TEST_PATTERN:
+ ret = ov01a10_test_pattern(ov01a10, ctrl->val);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ pm_runtime_put(&client->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops ov01a10_ctrl_ops = {
+ .s_ctrl = ov01a10_set_ctrl,
+};
+
+static int ov01a10_init_controls(struct ov01a10 *ov01a10)
+{
+ struct v4l2_ctrl_handler *ctrl_hdlr;
+ const struct ov01a10_mode *cur_mode;
+ s64 exposure_max, h_blank;
+ u32 vblank_min, vblank_max, vblank_default;
+ int size;
+ int ret = 0;
+
+ ctrl_hdlr = &ov01a10->ctrl_handler;
+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);
+ if (ret)
+ return ret;
+
+ ctrl_hdlr->lock = &ov01a10->mutex;
+ cur_mode = ov01a10->cur_mode;
+ size = ARRAY_SIZE(link_freq_menu_items);
+
+ ov01a10->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
+ &ov01a10_ctrl_ops,
+ V4L2_CID_LINK_FREQ,
+ size - 1, 0,
+ link_freq_menu_items);
+ if (ov01a10->link_freq)
+ ov01a10->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ ov01a10->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops,
+ V4L2_CID_PIXEL_RATE, 0,
+ OV01A10_SCLK, 1, OV01A10_SCLK);
+
+ vblank_min = cur_mode->vts_min - cur_mode->height;
+ vblank_max = OV01A10_VTS_MAX - cur_mode->height;
+ vblank_default = cur_mode->vts_def - cur_mode->height;
+ ov01a10->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops,
+ V4L2_CID_VBLANK, vblank_min,
+ vblank_max, 1, vblank_default);
+
+ h_blank = cur_mode->hts - cur_mode->width;
+ ov01a10->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops,
+ V4L2_CID_HBLANK, h_blank, h_blank,
+ 1, h_blank);
+ if (ov01a10->hblank)
+ ov01a10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
+ OV01A10_ANAL_GAIN_MIN, OV01A10_ANAL_GAIN_MAX,
+ OV01A10_ANAL_GAIN_STEP, OV01A10_ANAL_GAIN_MIN);
+ v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
+ OV01A10_DGTL_GAIN_MIN, OV01A10_DGTL_GAIN_MAX,
+ OV01A10_DGTL_GAIN_STEP, OV01A10_DGTL_GAIN_DEFAULT);
+ exposure_max = cur_mode->vts_def - OV01A10_EXPOSURE_MAX_MARGIN;
+ ov01a10->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops,
+ V4L2_CID_EXPOSURE,
+ OV01A10_EXPOSURE_MIN,
+ exposure_max,
+ OV01A10_EXPOSURE_STEP,
+ exposure_max);
+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov01a10_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(ov01a10_test_pattern_menu) - 1,
+ 0, 0, ov01a10_test_pattern_menu);
+ if (ctrl_hdlr->error)
+ return ctrl_hdlr->error;
+
+ ov01a10->sd.ctrl_handler = ctrl_hdlr;
+
+ return 0;
+}
+
+static void ov01a10_update_pad_format(const struct ov01a10_mode *mode,
+ struct v4l2_mbus_framefmt *fmt)
+{
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+ fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ fmt->field = V4L2_FIELD_NONE;
+}
+
+static int ov01a10_start_streaming(struct ov01a10 *ov01a10)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ const struct ov01a10_reg_list *reg_list;
+ int link_freq_index;
+ int ret = 0;
+
+ link_freq_index = ov01a10->cur_mode->link_freq_index;
+ reg_list = &link_freq_configs[link_freq_index].reg_list;
+ ret = ov01a10_write_reg_list(ov01a10, reg_list);
+ if (ret) {
+ dev_err(&client->dev, "failed to set plls");
+ return ret;
+ }
+
+ reg_list = &ov01a10->cur_mode->reg_list;
+ ret = ov01a10_write_reg_list(ov01a10, reg_list);
+ if (ret) {
+ dev_err(&client->dev, "failed to set mode");
+ return ret;
+ }
+
+ ret = __v4l2_ctrl_handler_setup(ov01a10->sd.ctrl_handler);
+ if (ret)
+ return ret;
+
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_MODE_SELECT, 1,
+ OV01A10_MODE_STREAMING);
+ if (ret)
+ dev_err(&client->dev, "failed to start streaming");
+
+ return ret;
+}
+
+static void ov01a10_stop_streaming(struct ov01a10 *ov01a10)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ int ret = 0;
+
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_MODE_SELECT, 1,
+ OV01A10_MODE_STANDBY);
+ if (ret)
+ dev_err(&client->dev, "failed to stop streaming");
+}
+
+static int ov01a10_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int ret = 0;
+
+ if (ov01a10->streaming == enable)
+ return 0;
+
+ mutex_lock(&ov01a10->mutex);
+ if (enable) {
+ ret = pm_runtime_get_sync(&client->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(&client->dev);
+ mutex_unlock(&ov01a10->mutex);
+ return ret;
+ }
+
+ ret = ov01a10_start_streaming(ov01a10);
+ if (ret) {
+ enable = 0;
+ ov01a10_stop_streaming(ov01a10);
+ pm_runtime_put(&client->dev);
+ }
+ } else {
+ ov01a10_stop_streaming(ov01a10);
+ pm_runtime_put(&client->dev);
+ }
+
+ ov01a10->streaming = enable;
+ mutex_unlock(&ov01a10->mutex);
+
+ return ret;
+}
+
+static int __maybe_unused ov01a10_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+
+ mutex_lock(&ov01a10->mutex);
+ if (ov01a10->streaming)
+ ov01a10_stop_streaming(ov01a10);
+
+ mutex_unlock(&ov01a10->mutex);
+
+ return 0;
+}
+
+static int __maybe_unused ov01a10_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+ int ret = 0;
+
+ mutex_lock(&ov01a10->mutex);
+ if (!ov01a10->streaming)
+ goto exit;
+
+ ret = ov01a10_start_streaming(ov01a10);
+ if (ret) {
+ ov01a10->streaming = false;
+ ov01a10_stop_streaming(ov01a10);
+ }
+
+exit:
+ mutex_unlock(&ov01a10->mutex);
+ return ret;
+}
+
+static int ov01a10_set_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+ const struct ov01a10_mode *mode;
+ s32 vblank_def, h_blank;
+
+ mode = v4l2_find_nearest_size(supported_modes,
+ ARRAY_SIZE(supported_modes), width,
+ height, fmt->format.width,
+ fmt->format.height);
+
+ mutex_lock(&ov01a10->mutex);
+ ov01a10_update_pad_format(mode, &fmt->format);
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
+ } else {
+ ov01a10->cur_mode = mode;
+ __v4l2_ctrl_s_ctrl(ov01a10->link_freq, mode->link_freq_index);
+ __v4l2_ctrl_s_ctrl_int64(ov01a10->pixel_rate, OV01A10_SCLK);
+
+ /* Update limits and set FPS to default */
+ vblank_def = mode->vts_def - mode->height;
+ __v4l2_ctrl_modify_range(ov01a10->vblank,
+ mode->vts_min - mode->height,
+ OV01A10_VTS_MAX - mode->height, 1,
+ vblank_def);
+ __v4l2_ctrl_s_ctrl(ov01a10->vblank, vblank_def);
+ h_blank = mode->hts - mode->width;
+ __v4l2_ctrl_modify_range(ov01a10->hblank, h_blank, h_blank, 1,
+ h_blank);
+ }
+ mutex_unlock(&ov01a10->mutex);
+
+ return 0;
+}
+
+static int ov01a10_get_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+
+ mutex_lock(&ov01a10->mutex);
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+ fmt->format = *v4l2_subdev_get_try_format(&ov01a10->sd,
+ sd_state, fmt->pad);
+ else
+ ov01a10_update_pad_format(ov01a10->cur_mode, &fmt->format);
+
+ mutex_unlock(&ov01a10->mutex);
+
+ return 0;
+}
+
+static int ov01a10_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 = MEDIA_BUS_FMT_SBGGR10_1X10;
+
+ return 0;
+}
+
+static int ov01a10_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->index >= ARRAY_SIZE(supported_modes))
+ return -EINVAL;
+
+ if (fse->code != MEDIA_BUS_FMT_SBGGR10_1X10)
+ return -EINVAL;
+
+ fse->min_width = supported_modes[fse->index].width;
+ fse->max_width = fse->min_width;
+ fse->min_height = supported_modes[fse->index].height;
+ fse->max_height = fse->min_height;
+
+ return 0;
+}
+
+static int ov01a10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+
+ mutex_lock(&ov01a10->mutex);
+ ov01a10_update_pad_format(&supported_modes[0],
+ v4l2_subdev_get_try_format(sd, fh->state, 0));
+ mutex_unlock(&ov01a10->mutex);
+
+ return 0;
+}
+
+static const struct v4l2_subdev_video_ops ov01a10_video_ops = {
+ .s_stream = ov01a10_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops ov01a10_pad_ops = {
+ .set_fmt = ov01a10_set_format,
+ .get_fmt = ov01a10_get_format,
+ .enum_mbus_code = ov01a10_enum_mbus_code,
+ .enum_frame_size = ov01a10_enum_frame_size,
+};
+
+static const struct v4l2_subdev_ops ov01a10_subdev_ops = {
+ .video = &ov01a10_video_ops,
+ .pad = &ov01a10_pad_ops,
+};
+
+static const struct media_entity_operations ov01a10_subdev_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static const struct v4l2_subdev_internal_ops ov01a10_internal_ops = {
+ .open = ov01a10_open,
+};
+
+static int ov01a10_identify_module(struct ov01a10 *ov01a10)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ int ret;
+ u32 val;
+
+ ret = ov01a10_read_reg(ov01a10, OV01A10_REG_CHIP_ID, 3, &val);
+ if (ret)
+ return ret;
+
+ if (val != OV01A10_CHIP_ID) {
+ dev_err(&client->dev, "chip id mismatch: %x!=%x",
+ OV01A10_CHIP_ID, val);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static int ov01a10_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+ pm_runtime_disable(&client->dev);
+ mutex_destroy(&ov01a10->mutex);
+
+ return 0;
+}
+
+static int ov01a10_probe(struct i2c_client *client)
+{
+ struct ov01a10 *ov01a10;
+ int ret = 0;
+ struct vsc_mipi_config conf;
+ struct vsc_camera_status status;
+ s64 link_freq;
+
+ conf.lane_num = OV01A10_DATA_LANES;
+ /* frequency unit 100k */
+ conf.freq = OV01A10_LINK_FREQ_400MHZ / 100000;
+ ret = vsc_acquire_camera_sensor(&conf, NULL, NULL, &status);
+ if (ret == -EAGAIN)
+ return -EPROBE_DEFER;
+ else if (ret) {
+ dev_err(&client->dev, "Acquire VSC failed.\n");
+ return ret;
+ }
+ ov01a10 = devm_kzalloc(&client->dev, sizeof(*ov01a10), GFP_KERNEL);
+ if (!ov01a10) {
+ ret = -ENOMEM;
+ goto probe_error_ret;
+ }
+
+ v4l2_i2c_subdev_init(&ov01a10->sd, client, &ov01a10_subdev_ops);
+
+ ret = ov01a10_identify_module(ov01a10);
+ if (ret) {
+ dev_err(&client->dev, "failed to find sensor: %d", ret);
+ goto probe_error_ret;
+ }
+
+ mutex_init(&ov01a10->mutex);
+ ov01a10->cur_mode = &supported_modes[0];
+ ret = ov01a10_init_controls(ov01a10);
+ if (ret) {
+ dev_err(&client->dev, "failed to init controls: %d", ret);
+ goto probe_error_v4l2_ctrl_handler_free;
+ }
+
+ ov01a10->sd.internal_ops = &ov01a10_internal_ops;
+ ov01a10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ ov01a10->sd.entity.ops = &ov01a10_subdev_entity_ops;
+ ov01a10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ ov01a10->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_pads_init(&ov01a10->sd.entity, 1, &ov01a10->pad);
+ if (ret) {
+ dev_err(&client->dev, "failed to init entity pads: %d", ret);
+ goto probe_error_v4l2_ctrl_handler_free;
+ }
+
+ ret = v4l2_async_register_subdev_sensor(&ov01a10->sd);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to register V4L2 subdev: %d",
+ ret);
+ goto probe_error_media_entity_cleanup;
+ }
+
+ vsc_release_camera_sensor(&status);
+ /*
+ * Device is already turned on by i2c-core with ACPI domain PM.
+ * Enable runtime PM and turn off the device.
+ */
+ pm_runtime_set_active(&client->dev);
+ pm_runtime_enable(&client->dev);
+ pm_runtime_idle(&client->dev);
+
+ return 0;
+
+probe_error_media_entity_cleanup:
+ media_entity_cleanup(&ov01a10->sd.entity);
+
+probe_error_v4l2_ctrl_handler_free:
+ v4l2_ctrl_handler_free(ov01a10->sd.ctrl_handler);
+ mutex_destroy(&ov01a10->mutex);
+
+probe_error_ret:
+ vsc_release_camera_sensor(&status);
+ return ret;
+}
+
+static const struct dev_pm_ops ov01a10_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ov01a10_suspend, ov01a10_resume)
+};
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id ov01a10_acpi_ids[] = {
+ {"OVTI01A0"},
+ {}
+};
+
+MODULE_DEVICE_TABLE(acpi, ov01a10_acpi_ids);
+#endif
+
+static struct i2c_driver ov01a10_i2c_driver = {
+ .driver = {
+ .name = "ov01a10",
+ .pm = &ov01a10_pm_ops,
+ .acpi_match_table = ACPI_PTR(ov01a10_acpi_ids),
+ },
+ .probe_new = ov01a10_probe,
+ .remove = ov01a10_remove,
+};
+
+module_i2c_driver(ov01a10_i2c_driver);
+
+MODULE_AUTHOR("Wang Yating <yating.wang at intel.com>");
+MODULE_DESCRIPTION("OmniVision OV01A10 sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/ov01a1s.c b/drivers/media/i2c/ov01a1s.c
index dd299204d9e9..2bda3122ff47 100644
--- a/drivers/media/i2c/ov01a1s.c
+++ b/drivers/media/i2c/ov01a1s.c
@@ -7,10 +7,12 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
+#include <linux/version.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include "power_ctrl_logic.h"
+#include <linux/vsc.h>
#define OV01A1S_LINK_FREQ_400MHZ 400000000ULL
#define OV01A1S_SCLK 40000000LL
@@ -677,7 +679,7 @@ static int __maybe_unused ov01a1s_resume(struct device *dev)
}
static int ov01a1s_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct ov01a1s *ov01a1s = to_ov01a1s(sd);
@@ -692,7 +694,7 @@ static int ov01a1s_set_format(struct v4l2_subdev *sd,
mutex_lock(&ov01a1s->mutex);
ov01a1s_update_pad_format(mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
+ *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
} else {
ov01a1s->cur_mode = mode;
__v4l2_ctrl_s_ctrl(ov01a1s->link_freq, mode->link_freq_index);
@@ -715,15 +717,15 @@ static int ov01a1s_set_format(struct v4l2_subdev *sd,
}
static int ov01a1s_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct ov01a1s *ov01a1s = to_ov01a1s(sd);
mutex_lock(&ov01a1s->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&ov01a1s->sd, cfg,
- fmt->pad);
+ fmt->format = *v4l2_subdev_get_try_format(&ov01a1s->sd,
+ sd_state, fmt->pad);
else
ov01a1s_update_pad_format(ov01a1s->cur_mode, &fmt->format);
@@ -733,7 +735,7 @@ static int ov01a1s_get_format(struct v4l2_subdev *sd,
}
static int ov01a1s_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index > 0)
@@ -745,7 +747,7 @@ static int ov01a1s_enum_mbus_code(struct v4l2_subdev *sd,
}
static int ov01a1s_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
if (fse->index >= ARRAY_SIZE(supported_modes))
@@ -768,7 +770,7 @@ static int ov01a1s_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&ov01a1s->mutex);
ov01a1s_update_pad_format(&supported_modes[0],
- v4l2_subdev_get_try_format(sd, fh->pad, 0));
+ v4l2_subdev_get_try_format(sd, fh->state, 0));
mutex_unlock(&ov01a1s->mutex);
return 0;
@@ -835,11 +837,20 @@ static int ov01a1s_probe(struct i2c_client *client)
{
struct ov01a1s *ov01a1s;
int ret = 0;
-
- if (power_ctrl_logic_set_power(1)) {
- dev_dbg(&client->dev, "power control driver not ready.\n");
+ struct vsc_mipi_config conf;
+ struct vsc_camera_status status;
+ s64 link_freq;
+
+ conf.lane_num = OV01A1S_DATA_LANES;
+ /* frequency unit 100k */
+ conf.freq = OV01A1S_LINK_FREQ_400MHZ / 100000;
+ ret = vsc_acquire_camera_sensor(&conf, NULL, NULL, &status);
+ if (ret == -EAGAIN)
+ ret = power_ctrl_logic_set_power(1);
+ if (ret == -EAGAIN)
return -EPROBE_DEFER;
- }
+ else if (ret)
+ return ret;
ov01a1s = devm_kzalloc(&client->dev, sizeof(*ov01a1s), GFP_KERNEL);
if (!ov01a1s) {
ret = -ENOMEM;
@@ -879,6 +890,7 @@ static int ov01a1s_probe(struct i2c_client *client)
goto probe_error_media_entity_cleanup;
}
+ vsc_release_camera_sensor(&status);
/*
* Device is already turned on by i2c-core with ACPI domain PM.
* Enable runtime PM and turn off the device.
@@ -899,6 +911,7 @@ static int ov01a1s_probe(struct i2c_client *client)
probe_error_ret:
power_ctrl_logic_set_power(0);
+ vsc_release_camera_sensor(&status);
return ret;
}
diff --git a/drivers/media/i2c/power_ctrl_logic.c b/drivers/media/i2c/power_ctrl_logic.c
index 1ccd94f9e97e..90ee1e23d6ea 100644
--- a/drivers/media/i2c/power_ctrl_logic.c
+++ b/drivers/media/i2c/power_ctrl_logic.c
@@ -126,7 +126,7 @@ int power_ctrl_logic_set_power(int on)
pr_debug("@%s,failed to set power, gpio_ready=%d, on=%d\n",
__func__, pcl.gpio_ready, on);
mutex_unlock(&pcl.status_lock);
- return -EPROBE_DEFER;
+ return -EAGAIN;
}
if (pcl.power_on != on) {
gpiod_set_value_cansleep(pcl.reset_gpio, on);
diff --git a/drivers/media/pci/intel/Kconfig b/drivers/media/pci/intel/Kconfig
index defdca369fb5..ee4a77acb66f 100644
--- a/drivers/media/pci/intel/Kconfig
+++ b/drivers/media/pci/intel/Kconfig
@@ -3,10 +3,9 @@ config VIDEO_INTEL_IPU6
depends on ACPI
depends on MEDIA_SUPPORT
depends on MEDIA_PCI_SUPPORT
- depends on X86_64
select IOMMU_API
select IOMMU_IOVA
- select X86_DEV_DMA_OPS
+ select X86_DEV_DMA_OPS if X86
select VIDEOBUF2_DMA_CONTIG
select V4L2_FWNODE
select PHYS_ADDR_T_64BIT
diff --git a/drivers/media/pci/intel/ipu-buttress.c b/drivers/media/pci/intel/ipu-buttress.c
index eac4a43ed7b1..bf0b7916b381 100644
--- a/drivers/media/pci/intel/ipu-buttress.c
+++ b/drivers/media/pci/intel/ipu-buttress.c
@@ -893,7 +893,6 @@ int ipu_buttress_authenticate(struct ipu_device *isp)
return rval;
}
-EXPORT_SYMBOL(ipu_buttress_authenticate);
static int ipu_buttress_send_tsc_request(struct ipu_device *isp)
{
@@ -963,50 +962,25 @@ struct clk_ipu_sensor {
int ipu_buttress_tsc_read(struct ipu_device *isp, u64 *val)
{
- struct ipu_buttress *b = &isp->buttress;
- u32 tsc_hi, tsc_lo_1, tsc_lo_2, tsc_lo_3, tsc_chk = 0;
+ u32 tsc_hi_1, tsc_hi_2, tsc_lo;
unsigned long flags;
- short retry = IPU_BUTTRESS_TSC_RETRY;
-
- do {
- spin_lock_irqsave(&b->tsc_lock, flags);
- tsc_hi = readl(isp->base + BUTTRESS_REG_TSC_HI);
-
- /*
- * We are occasionally getting broken values from
- * HH. Reading 3 times and doing sanity check as a WA
- */
- tsc_lo_1 = readl(isp->base + BUTTRESS_REG_TSC_LO);
- tsc_lo_2 = readl(isp->base + BUTTRESS_REG_TSC_LO);
- tsc_lo_3 = readl(isp->base + BUTTRESS_REG_TSC_LO);
- tsc_chk = readl(isp->base + BUTTRESS_REG_TSC_HI);
- spin_unlock_irqrestore(&b->tsc_lock, flags);
- if (tsc_chk == tsc_hi && tsc_lo_2 &&
- tsc_lo_2 - tsc_lo_1 <= IPU_BUTTRESS_TSC_LIMIT &&
- tsc_lo_3 - tsc_lo_2 <= IPU_BUTTRESS_TSC_LIMIT) {
- *val = (u64)tsc_hi << 32 | tsc_lo_2;
- return 0;
- }
- /*
- * Trace error only if limit checkings fails at least
- * by two consecutive readings.
- */
- if (retry < IPU_BUTTRESS_TSC_RETRY - 1 && tsc_lo_2)
- dev_err(&isp->pdev->dev,
- "%s = %u, %s = %u, %s = %u, %s = %u, %s = %u",
- "failure: tsc_hi", tsc_hi,
- "tsc_chk", tsc_chk,
- "tsc_lo_1", tsc_lo_1,
- "tsc_lo_2", tsc_lo_2, "tsc_lo_3", tsc_lo_3);
- } while (retry--);
-
- if (!tsc_chk && !tsc_lo_2)
- return -EIO;
-
- WARN_ON_ONCE(1);
+ local_irq_save(flags);
+ tsc_hi_1 = readl(isp->base + BUTTRESS_REG_TSC_HI);
+ tsc_lo = readl(isp->base + BUTTRESS_REG_TSC_LO);
+ tsc_hi_2 = readl(isp->base + BUTTRESS_REG_TSC_HI);
+ if (tsc_hi_1 == tsc_hi_2) {
+ *val = (u64)tsc_hi_1 << 32 | tsc_lo;
+ } else {
+ /* Check if TSC has rolled over */
+ if (tsc_lo & BIT(31))
+ *val = (u64)tsc_hi_1 << 32 | tsc_lo;
+ else
+ *val = (u64)tsc_hi_2 << 32 | tsc_lo;
+ }
+ local_irq_restore(flags);
- return -EINVAL;
+ return 0;
}
EXPORT_SYMBOL_GPL(ipu_buttress_tsc_read);
@@ -1299,7 +1273,6 @@ int ipu_buttress_init(struct ipu_device *isp)
mutex_init(&b->auth_mutex);
mutex_init(&b->cons_mutex);
mutex_init(&b->ipc_mutex);
- spin_lock_init(&b->tsc_lock);
init_completion(&b->ish.send_complete);
init_completion(&b->cse.send_complete);
init_completion(&b->ish.recv_complete);
diff --git a/drivers/media/pci/intel/ipu-buttress.h b/drivers/media/pci/intel/ipu-buttress.h
index e1d054c3cd07..b57f4aaffa57 100644
--- a/drivers/media/pci/intel/ipu-buttress.h
+++ b/drivers/media/pci/intel/ipu-buttress.h
@@ -58,7 +58,6 @@ struct ipu_buttress_ipc {
struct ipu_buttress {
struct mutex power_mutex, auth_mutex, cons_mutex, ipc_mutex;
- spinlock_t tsc_lock; /* tsc lock */
struct ipu_buttress_ipc cse;
struct ipu_buttress_ipc ish;
struct list_head constraints;
diff --git a/drivers/media/pci/intel/ipu-isys-csi2-be-soc.c b/drivers/media/pci/intel/ipu-isys-csi2-be-soc.c
index daaed97d1b13..7072500d930a 100644
--- a/drivers/media/pci/intel/ipu-isys-csi2-be-soc.c
+++ b/drivers/media/pci/intel/ipu-isys-csi2-be-soc.c
@@ -116,7 +116,7 @@ __subdev_link_validate(struct v4l2_subdev *sd, struct media_link *link,
static int
ipu_isys_csi2_be_soc_set_sel(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
struct ipu_isys_subdev *asd = to_ipu_isys_subdev(sd);
@@ -128,7 +128,7 @@ ipu_isys_csi2_be_soc_set_sel(struct v4l2_subdev *sd,
enum isys_subdev_prop_tgt tgt =
IPU_ISYS_SUBDEV_PROP_TGT_SOURCE_CROP;
struct v4l2_mbus_framefmt *ffmt =
- __ipu_isys_get_ffmt(sd, cfg, sel->pad, sel->which);
+ __ipu_isys_get_ffmt(sd, sd_state, sel->pad, sel->which);
if (get_supported_code_index(ffmt->code) < 0) {
/* Non-bayer formats can't be odd lines cropped */
@@ -142,9 +142,9 @@ ipu_isys_csi2_be_soc_set_sel(struct v4l2_subdev *sd,
sel->r.height = clamp(sel->r.height, IPU_ISYS_MIN_HEIGHT,
IPU_ISYS_MAX_HEIGHT);
- *__ipu_isys_get_selection(sd, cfg, sel->target, sel->pad,
+ *__ipu_isys_get_selection(sd, sd_state, sel->target, sel->pad,
sel->which) = sel->r;
- ipu_isys_subdev_fmt_propagate(sd, cfg, NULL, &sel->r,
+ ipu_isys_subdev_fmt_propagate(sd, sd_state, NULL, &sel->r,
tgt, sel->pad, sel->which);
return 0;
}
@@ -171,11 +171,11 @@ static struct media_entity_operations csi2_be_soc_entity_ops = {
};
static void csi2_be_soc_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct v4l2_mbus_framefmt *ffmt =
- __ipu_isys_get_ffmt(sd, cfg, fmt->pad,
+ __ipu_isys_get_ffmt(sd, sd_state, fmt->pad,
fmt->which);
if (sd->entity.pads[fmt->pad].flags & MEDIA_PAD_FL_SINK) {
@@ -183,19 +183,19 @@ static void csi2_be_soc_set_ffmt(struct v4l2_subdev *sd,
fmt->format.field = V4L2_FIELD_NONE;
*ffmt = fmt->format;
- ipu_isys_subdev_fmt_propagate(sd, cfg, &fmt->format,
+ ipu_isys_subdev_fmt_propagate(sd, sd_state, &fmt->format,
NULL,
IPU_ISYS_SUBDEV_PROP_TGT_SINK_FMT,
fmt->pad, fmt->which);
} else if (sd->entity.pads[fmt->pad].flags & MEDIA_PAD_FL_SOURCE) {
struct v4l2_mbus_framefmt *sink_ffmt;
- struct v4l2_rect *r = __ipu_isys_get_selection(sd, cfg,
+ struct v4l2_rect *r = __ipu_isys_get_selection(sd, sd_state,
V4L2_SEL_TGT_CROP, fmt->pad, fmt->which);
struct ipu_isys_subdev *asd = to_ipu_isys_subdev(sd);
u32 code;
int idx;
- sink_ffmt = __ipu_isys_get_ffmt(sd, cfg, 0, fmt->which);
+ sink_ffmt = __ipu_isys_get_ffmt(sd, sd_state, 0, fmt->which);
code = sink_ffmt->code;
idx = get_supported_code_index(code);
diff --git a/drivers/media/pci/intel/ipu-isys-csi2-be.c b/drivers/media/pci/intel/ipu-isys-csi2-be.c
new file mode 100644
index 000000000000..1ef87fe3dee8
--- /dev/null
+++ b/drivers/media/pci/intel/ipu-isys-csi2-be.c
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2014 - 2020 Intel Corporation
+
+#include <linux/device.h>
+#include <linux/module.h>
+
+#include <media/ipu-isys.h>
+#include <media/media-entity.h>
+#include <media/v4l2-device.h>
+
+#include "ipu.h"
+#include "ipu-bus.h"
+#include "ipu-isys.h"
+#include "ipu-isys-csi2-be.h"
+#include "ipu-isys-subdev.h"
+#include "ipu-isys-video.h"
+
+/*
+ * Raw bayer format pixel order MUST BE MAINTAINED in groups of four codes.
+ * Otherwise pixel order calculation below WILL BREAK!
+ */
+static const u32 csi2_be_supported_codes_pad[] = {
+ MEDIA_BUS_FMT_SBGGR12_1X12,
+ MEDIA_BUS_FMT_SGBRG12_1X12,
+ MEDIA_BUS_FMT_SGRBG12_1X12,
+ MEDIA_BUS_FMT_SRGGB12_1X12,
+ MEDIA_BUS_FMT_SBGGR10_1X10,
+ MEDIA_BUS_FMT_SGBRG10_1X10,
+ MEDIA_BUS_FMT_SGRBG10_1X10,
+ MEDIA_BUS_FMT_SRGGB10_1X10,
+ MEDIA_BUS_FMT_SBGGR8_1X8,
+ MEDIA_BUS_FMT_SGBRG8_1X8,
+ MEDIA_BUS_FMT_SGRBG8_1X8,
+ MEDIA_BUS_FMT_SRGGB8_1X8,
+ 0,
+};
+
+static const u32 *csi2_be_supported_codes[] = {
+ csi2_be_supported_codes_pad,
+ csi2_be_supported_codes_pad,
+};
+
+static struct v4l2_subdev_internal_ops csi2_be_sd_internal_ops = {
+ .open = ipu_isys_subdev_open,
+ .close = ipu_isys_subdev_close,
+};
+
+static const struct v4l2_subdev_core_ops csi2_be_sd_core_ops = {
+};
+
+static const struct v4l2_ctrl_config compression_ctrl_cfg = {
+ .ops = NULL,
+ .id = V4L2_CID_IPU_ISYS_COMPRESSION,
+ .name = "ISYS CSI-BE compression",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 0,
+};
+
+static int set_stream(struct v4l2_subdev *sd, int enable)
+{
+ return 0;
+}
+
+static const struct v4l2_subdev_video_ops csi2_be_sd_video_ops = {
+ .s_stream = set_stream,
+};
+
+static int __subdev_link_validate(struct v4l2_subdev *sd,
+ struct media_link *link,
+ struct v4l2_subdev_format *source_fmt,
+ struct v4l2_subdev_format *sink_fmt)
+{
+ struct ipu_isys_pipeline *ip = container_of(sd->entity.pipe,
+ struct ipu_isys_pipeline,
+ pipe);
+
+ ip->csi2_be = to_ipu_isys_csi2_be(sd);
+ return ipu_isys_subdev_link_validate(sd, link, source_fmt, sink_fmt);
+}
+
+static int get_supported_code_index(u32 code)
+{
+ int i;
+
+ for (i = 0; csi2_be_supported_codes_pad[i]; i++) {
+ if (csi2_be_supported_codes_pad[i] == code)
+ return i;
+ }
+ return -EINVAL;
+}
+
+static int ipu_isys_csi2_be_set_sel(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_selection *sel)
+{
+ struct ipu_isys_subdev *asd = to_ipu_isys_subdev(sd);
+ struct media_pad *pad = &asd->sd.entity.pads[sel->pad];
+
+ if (sel->target == V4L2_SEL_TGT_CROP &&
+ pad->flags & MEDIA_PAD_FL_SOURCE &&
+ asd->valid_tgts[CSI2_BE_PAD_SOURCE].crop) {
+ struct v4l2_mbus_framefmt *ffmt =
+ __ipu_isys_get_ffmt(sd, sd_state, sel->pad, sel->which);
+ struct v4l2_rect *r = __ipu_isys_get_selection
+ (sd, sd_state, sel->target, CSI2_BE_PAD_SINK, sel->which);
+
+ if (get_supported_code_index(ffmt->code) < 0) {
+ /* Non-bayer formats can't be single line cropped */
+ sel->r.left &= ~1;
+ sel->r.top &= ~1;
+
+ /* Non-bayer formats can't pe padded at all */
+ sel->r.width = clamp(sel->r.width,
+ IPU_ISYS_MIN_WIDTH, r->width);
+ } else {
+ sel->r.width = clamp(sel->r.width,
+ IPU_ISYS_MIN_WIDTH,
+ IPU_ISYS_MAX_WIDTH);
+ }
+
+ /*
+ * Vertical padding is not supported, height is
+ * restricted by sink pad resolution.
+ */
+ sel->r.height = clamp(sel->r.height, IPU_ISYS_MIN_HEIGHT,
+ r->height);
+ *__ipu_isys_get_selection(sd, sd_state, sel->target,
+ sel->pad, sel->which) = sel->r;
+ ipu_isys_subdev_fmt_propagate
+ (sd, sd_state, NULL, &sel->r,
+ IPU_ISYS_SUBDEV_PROP_TGT_SOURCE_CROP,
+ sel->pad, sel->which);
+ return 0;
+ }
+ return ipu_isys_subdev_set_sel(sd, sd_state, sel);
+}
+
+static const struct v4l2_subdev_pad_ops csi2_be_sd_pad_ops = {
+ .link_validate = __subdev_link_validate,
+ .get_fmt = ipu_isys_subdev_get_ffmt,
+ .set_fmt = ipu_isys_subdev_set_ffmt,
+ .get_selection = ipu_isys_subdev_get_sel,
+ .set_selection = ipu_isys_csi2_be_set_sel,
+ .enum_mbus_code = ipu_isys_subdev_enum_mbus_code,
+};
+
+static struct v4l2_subdev_ops csi2_be_sd_ops = {
+ .core = &csi2_be_sd_core_ops,
+ .video = &csi2_be_sd_video_ops,
+ .pad = &csi2_be_sd_pad_ops,
+};
+
+static struct media_entity_operations csi2_be_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static void csi2_be_set_ffmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct ipu_isys_csi2 *csi2 = to_ipu_isys_csi2(sd);
+ struct v4l2_mbus_framefmt *ffmt =
+ __ipu_isys_get_ffmt(sd, sd_state, fmt->pad, fmt->which);
+
+ switch (fmt->pad) {
+ case CSI2_BE_PAD_SINK:
+ if (fmt->format.field != V4L2_FIELD_ALTERNATE)
+ fmt->format.field = V4L2_FIELD_NONE;
+ *ffmt = fmt->format;
+
+ ipu_isys_subdev_fmt_propagate
+ (sd, sd_state, &fmt->format, NULL,
+ IPU_ISYS_SUBDEV_PROP_TGT_SINK_FMT, fmt->pad, fmt->which);
+ return;
+ case CSI2_BE_PAD_SOURCE: {
+ struct v4l2_mbus_framefmt *sink_ffmt =
+ __ipu_isys_get_ffmt(sd, sd_state, CSI2_BE_PAD_SINK,
+ fmt->which);
+ struct v4l2_rect *r =
+ __ipu_isys_get_selection(sd, sd_state, V4L2_SEL_TGT_CROP,
+ CSI2_BE_PAD_SOURCE,
+ fmt->which);
+ struct ipu_isys_subdev *asd = to_ipu_isys_subdev(sd);
+ u32 code = sink_ffmt->code;
+ int idx = get_supported_code_index(code);
+
+ if (asd->valid_tgts[CSI2_BE_PAD_SOURCE].crop && idx >= 0) {
+ int crop_info = 0;
+
+ if (r->top & 1)
+ crop_info |= CSI2_BE_CROP_VER;
+ if (r->left & 1)
+ crop_info |= CSI2_BE_CROP_HOR;
+ code = csi2_be_supported_codes_pad
+ [((idx & CSI2_BE_CROP_MASK) ^ crop_info)
+ + (idx & ~CSI2_BE_CROP_MASK)];
+ }
+ ffmt->width = r->width;
+ ffmt->height = r->height;
+ ffmt->code = code;
+ ffmt->field = sink_ffmt->field;
+ return;
+ }
+ default:
+ dev_err(&csi2->isys->adev->dev, "Unknown pad type\n");
+ WARN_ON(1);
+ }
+}
+
+void ipu_isys_csi2_be_cleanup(struct ipu_isys_csi2_be *csi2_be)
+{
+ v4l2_ctrl_handler_free(&csi2_be->av.ctrl_handler);
+ v4l2_device_unregister_subdev(&csi2_be->asd.sd);
+ ipu_isys_subdev_cleanup(&csi2_be->asd);
+ ipu_isys_video_cleanup(&csi2_be->av);
+}
+
+int ipu_isys_csi2_be_init(struct ipu_isys_csi2_be *csi2_be,
+ struct ipu_isys *isys)
+{
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .pad = CSI2_BE_PAD_SINK,
+ .format = {
+ .width = 4096,
+ .height = 3072,
+ },
+ };
+ struct v4l2_subdev_selection sel = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .pad = CSI2_BE_PAD_SOURCE,
+ .target = V4L2_SEL_TGT_CROP,
+ .r = {
+ .width = fmt.format.width,
+ .height = fmt.format.height,
+ },
+ };
+ int rval;
+
+ csi2_be->asd.sd.entity.ops = &csi2_be_entity_ops;
+ csi2_be->asd.isys = isys;
+
+ rval = ipu_isys_subdev_init(&csi2_be->asd, &csi2_be_sd_ops, 0,
+ NR_OF_CSI2_BE_PADS,
+ NR_OF_CSI2_BE_SOURCE_PADS,
+ NR_OF_CSI2_BE_SINK_PADS, 0);
+ if (rval)
+ goto fail;
+
+ csi2_be->asd.pad[CSI2_BE_PAD_SINK].flags = MEDIA_PAD_FL_SINK
+ | MEDIA_PAD_FL_MUST_CONNECT;
+ csi2_be->asd.pad[CSI2_BE_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+ csi2_be->asd.valid_tgts[CSI2_BE_PAD_SOURCE].crop = true;
+ csi2_be->asd.set_ffmt = csi2_be_set_ffmt;
+
+ BUILD_BUG_ON(ARRAY_SIZE(csi2_be_supported_codes) != NR_OF_CSI2_BE_PADS);
+ csi2_be->asd.supported_codes = csi2_be_supported_codes;
+ csi2_be->asd.be_mode = IPU_BE_RAW;
+ csi2_be->asd.isl_mode = IPU_ISL_CSI2_BE;
+
+ ipu_isys_subdev_set_ffmt(&csi2_be->asd.sd, NULL, &fmt);
+ ipu_isys_csi2_be_set_sel(&csi2_be->asd.sd, NULL, &sel);
+
+ csi2_be->asd.sd.internal_ops = &csi2_be_sd_internal_ops;
+ snprintf(csi2_be->asd.sd.name, sizeof(csi2_be->asd.sd.name),
+ IPU_ISYS_ENTITY_PREFIX " CSI2 BE");
+ snprintf(csi2_be->av.vdev.name, sizeof(csi2_be->av.vdev.name),
+ IPU_ISYS_ENTITY_PREFIX " CSI2 BE capture");
+ csi2_be->av.aq.css_pin_type = IPU_FW_ISYS_PIN_TYPE_RAW_NS;
+ v4l2_set_subdevdata(&csi2_be->asd.sd, &csi2_be->asd);
+ rval = v4l2_device_register_subdev(&isys->v4l2_dev, &csi2_be->asd.sd);
+ if (rval) {
+ dev_info(&isys->adev->dev, "can't register v4l2 subdev\n");
+ goto fail;
+ }
+
+ csi2_be->av.isys = isys;
+ csi2_be->av.pfmts = ipu_isys_pfmts;
+ csi2_be->av.try_fmt_vid_mplane =
+ ipu_isys_video_try_fmt_vid_mplane_default;
+ csi2_be->av.prepare_fw_stream =
+ ipu_isys_prepare_fw_cfg_default;
+ csi2_be->av.aq.buf_prepare = ipu_isys_buf_prepare;
+ csi2_be->av.aq.fill_frame_buff_set_pin =
+ ipu_isys_buffer_to_fw_frame_buff_pin;
+ csi2_be->av.aq.link_fmt_validate = ipu_isys_link_fmt_validate;
+ csi2_be->av.aq.vbq.buf_struct_size =
+ sizeof(struct ipu_isys_video_buffer);
+
+ /* create v4l2 ctrl for csi-be video node */
+ rval = v4l2_ctrl_handler_init(&csi2_be->av.ctrl_handler, 0);
+ if (rval) {
+ dev_err(&isys->adev->dev,
+ "failed to init v4l2 ctrl handler for csi2_be\n");
+ goto fail;
+ }
+
+ csi2_be->av.compression_ctrl =
+ v4l2_ctrl_new_custom(&csi2_be->av.ctrl_handler,
+ &compression_ctrl_cfg, NULL);
+ if (!csi2_be->av.compression_ctrl) {
+ dev_err(&isys->adev->dev,
+ "failed to create CSI-BE cmprs ctrl\n");
+ goto fail;
+ }
+ csi2_be->av.compression = 0;
+ csi2_be->av.vdev.ctrl_handler = &csi2_be->av.ctrl_handler;
+
+ rval = ipu_isys_video_init(&csi2_be->av, &csi2_be->asd.sd.entity,
+ CSI2_BE_PAD_SOURCE, MEDIA_PAD_FL_SINK, 0);
+ if (rval) {
+ dev_info(&isys->adev->dev, "can't init video node\n");
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ ipu_isys_csi2_be_cleanup(csi2_be);
+
+ return rval;
+}
diff --git a/drivers/media/pci/intel/ipu-isys-csi2.c b/drivers/media/pci/intel/ipu-isys-csi2.c
index 1242a79718b1..e206200b6f4d 100644
--- a/drivers/media/pci/intel/ipu-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu-isys-csi2.c
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
-// Copyright (C) 2013 - 2020 Intel Corporation
+// Copyright (C) 2013 - 2021 Intel Corporation
#include <linux/device.h>
#include <linux/module.h>
#include <linux/version.h>
+#include <linux/vsc.h>
#include <media/ipu-isys.h>
#include <media/media-entity.h>
@@ -224,6 +225,9 @@ static int set_stream(struct v4l2_subdev *sd, int enable)
struct ipu_isys_csi2_timing timing = {0};
unsigned int nlanes;
int rval;
+ struct vsc_mipi_config conf;
+ struct vsc_camera_status status;
+ s64 link_freq;
dev_dbg(&csi2->isys->adev->dev, "csi2 s_stream %d\n", enable);
@@ -236,6 +240,12 @@ static int set_stream(struct v4l2_subdev *sd, int enable)
if (!enable) {
ipu_isys_csi2_set_stream(sd, timing, 0, enable);
+ rval = vsc_release_camera_sensor(&status);
+ if (rval && rval != -EAGAIN) {
+ dev_err(&csi2->isys->adev->dev,
+ "Release VSC failed.\n");
+ return rval;
+ }
return 0;
}
@@ -250,6 +260,20 @@ static int set_stream(struct v4l2_subdev *sd, int enable)
return rval;
rval = ipu_isys_csi2_set_stream(sd, timing, nlanes, enable);
+ rval = ipu_isys_csi2_get_link_freq(csi2, &link_freq);
+ if (rval)
+ return rval;
+
+ conf.lane_num = nlanes;
+ /* frequency unit 100k */
+ conf.freq = link_freq / 100000;
+ rval = vsc_acquire_camera_sensor(&conf, NULL, NULL, &status);
+ if (rval && rval != -EAGAIN) {
+ dev_err(&csi2->isys->adev->dev, "Acquire VSC failed.\n");
+ return rval;
+ } else {
+ return 0;
+ }
return rval;
}
@@ -314,17 +338,17 @@ static const struct v4l2_subdev_video_ops csi2_sd_video_ops = {
};
static int ipu_isys_csi2_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
- return ipu_isys_subdev_get_ffmt(sd, cfg, fmt);
+ return ipu_isys_subdev_get_ffmt(sd, sd_state, fmt);
}
static int ipu_isys_csi2_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
- return ipu_isys_subdev_set_ffmt(sd, cfg, fmt);
+ return ipu_isys_subdev_set_ffmt(sd, sd_state, fmt);
}
static int __subdev_link_validate(struct v4l2_subdev *sd,
@@ -360,12 +384,12 @@ static struct media_entity_operations csi2_entity_ops = {
};
static void csi2_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
enum isys_subdev_prop_tgt tgt = IPU_ISYS_SUBDEV_PROP_TGT_SINK_FMT;
struct v4l2_mbus_framefmt *ffmt =
- __ipu_isys_get_ffmt(sd, cfg, fmt->pad,
+ __ipu_isys_get_ffmt(sd, sd_state, fmt->pad,
fmt->which);
if (fmt->format.field != V4L2_FIELD_ALTERNATE)
@@ -373,7 +397,7 @@ static void csi2_set_ffmt(struct v4l2_subdev *sd,
if (fmt->pad == CSI2_PAD_SINK) {
*ffmt = fmt->format;
- ipu_isys_subdev_fmt_propagate(sd, cfg, &fmt->format, NULL,
+ ipu_isys_subdev_fmt_propagate(sd, sd_state, &fmt->format, NULL,
tgt, fmt->pad, fmt->which);
return;
}
diff --git a/drivers/media/pci/intel/ipu-isys-subdev.c b/drivers/media/pci/intel/ipu-isys-subdev.c
index 71a5fa592d44..7f00fa817252 100644
--- a/drivers/media/pci/intel/ipu-isys-subdev.c
+++ b/drivers/media/pci/intel/ipu-isys-subdev.c
@@ -134,8 +134,7 @@ u32 ipu_isys_subdev_code_to_uncompressed(u32 sink_code)
}
struct v4l2_mbus_framefmt *__ipu_isys_get_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config
- *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int pad,
unsigned int which)
{
@@ -144,11 +143,11 @@ struct v4l2_mbus_framefmt *__ipu_isys_get_ffmt(struct v4l2_subdev *sd,
if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
return &asd->ffmt[pad];
else
- return v4l2_subdev_get_try_format(sd, cfg, pad);
+ return v4l2_subdev_get_try_format(sd, sd_state, pad);
}
struct v4l2_rect *__ipu_isys_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int target,
unsigned int pad, unsigned int which)
{
@@ -164,9 +163,9 @@ struct v4l2_rect *__ipu_isys_get_selection(struct v4l2_subdev *sd,
} else {
switch (target) {
case V4L2_SEL_TGT_CROP:
- return v4l2_subdev_get_try_crop(sd, cfg, pad);
+ return v4l2_subdev_get_try_crop(sd, sd_state, pad);
case V4L2_SEL_TGT_COMPOSE:
- return v4l2_subdev_get_try_compose(sd, cfg, pad);
+ return v4l2_subdev_get_try_compose(sd, sd_state, pad);
}
}
WARN_ON(1);
@@ -189,7 +188,7 @@ static int target_valid(struct v4l2_subdev *sd, unsigned int target,
}
int ipu_isys_subdev_fmt_propagate(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_mbus_framefmt *ffmt,
struct v4l2_rect *r,
enum isys_subdev_prop_tgt tgt,
@@ -228,12 +227,11 @@ int ipu_isys_subdev_fmt_propagate(struct v4l2_subdev *sd,
}
for (i = 0; i < sd->entity.num_pads; i++) {
- ffmts[i] = __ipu_isys_get_ffmt(sd, cfg, i, which);
- crops[i] = __ipu_isys_get_selection(sd, cfg, V4L2_SEL_TGT_CROP,
- i, which);
- compose[i] = __ipu_isys_get_selection(sd, cfg,
- V4L2_SEL_TGT_COMPOSE,
- i, which);
+ ffmts[i] = __ipu_isys_get_ffmt(sd, sd_state, i, which);
+ crops[i] = __ipu_isys_get_selection(sd, sd_state,
+ V4L2_SEL_TGT_CROP, i, which);
+ compose[i] = __ipu_isys_get_selection(sd, sd_state,
+ V4L2_SEL_TGT_COMPOSE, i, which);
}
switch (tgt) {
@@ -242,8 +240,8 @@ int ipu_isys_subdev_fmt_propagate(struct v4l2_subdev *sd,
crops[pad]->top = 0;
crops[pad]->width = ffmt->width;
crops[pad]->height = ffmt->height;
- rval = ipu_isys_subdev_fmt_propagate(sd, cfg, ffmt, crops[pad],
- tgt + 1, pad, which);
+ rval = ipu_isys_subdev_fmt_propagate(sd, sd_state, ffmt,
+ crops[pad], tgt + 1, pad, which);
goto out_subdev_fmt_propagate;
case IPU_ISYS_SUBDEV_PROP_TGT_SINK_CROP:
if (WARN_ON(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE))
@@ -253,9 +251,8 @@ int ipu_isys_subdev_fmt_propagate(struct v4l2_subdev *sd,
compose[pad]->top = 0;
compose[pad]->width = r->width;
compose[pad]->height = r->height;
- rval = ipu_isys_subdev_fmt_propagate(sd, cfg, ffmt,
- compose[pad], tgt + 1,
- pad, which);
+ rval = ipu_isys_subdev_fmt_propagate(sd, sd_state, ffmt,
+ compose[pad], tgt + 1, pad, which);
goto out_subdev_fmt_propagate;
case IPU_ISYS_SUBDEV_PROP_TGT_SINK_COMPOSE:
if (WARN_ON(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE)) {
@@ -272,11 +269,8 @@ int ipu_isys_subdev_fmt_propagate(struct v4l2_subdev *sd,
compose[i]->top = 0;
compose[i]->width = r->width;
compose[i]->height = r->height;
- rval = ipu_isys_subdev_fmt_propagate(sd, cfg,
- ffmt,
- compose[i],
- tgt + 1, i,
- which);
+ rval = ipu_isys_subdev_fmt_propagate(sd, sd_state,
+ ffmt, compose[i], tgt + 1, i, which);
if (rval)
goto out_subdev_fmt_propagate;
}
@@ -291,9 +285,8 @@ int ipu_isys_subdev_fmt_propagate(struct v4l2_subdev *sd,
crops[pad]->top = 0;
crops[pad]->width = r->width;
crops[pad]->height = r->height;
- rval = ipu_isys_subdev_fmt_propagate(sd, cfg, ffmt,
- crops[pad], tgt + 1,
- pad, which);
+ rval = ipu_isys_subdev_fmt_propagate(sd, sd_state, ffmt,
+ crops[pad], tgt + 1, pad, which);
goto out_subdev_fmt_propagate;
case IPU_ISYS_SUBDEV_PROP_TGT_SOURCE_CROP:{
struct v4l2_subdev_format fmt = {
@@ -313,7 +306,7 @@ int ipu_isys_subdev_fmt_propagate(struct v4l2_subdev *sd,
},
};
- asd->set_ffmt(sd, cfg, &fmt);
+ asd->set_ffmt(sd, sd_state, &fmt);
goto out_subdev_fmt_propagate;
}
}
@@ -326,16 +319,16 @@ int ipu_isys_subdev_fmt_propagate(struct v4l2_subdev *sd,
}
int ipu_isys_subdev_set_ffmt_default(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct v4l2_mbus_framefmt *ffmt =
- __ipu_isys_get_ffmt(sd, cfg, fmt->pad, fmt->which);
+ __ipu_isys_get_ffmt(sd, sd_state, fmt->pad, fmt->which);
/* No propagation for non-zero pads. */
if (fmt->pad) {
struct v4l2_mbus_framefmt *sink_ffmt =
- __ipu_isys_get_ffmt(sd, cfg, 0, fmt->which);
+ __ipu_isys_get_ffmt(sd, sd_state, 0, fmt->which);
ffmt->width = sink_ffmt->width;
ffmt->height = sink_ffmt->height;
@@ -350,18 +343,18 @@ int ipu_isys_subdev_set_ffmt_default(struct v4l2_subdev *sd,
ffmt->code = fmt->format.code;
ffmt->field = fmt->format.field;
- return ipu_isys_subdev_fmt_propagate(sd, cfg, &fmt->format, NULL,
+ return ipu_isys_subdev_fmt_propagate(sd, sd_state, &fmt->format, NULL,
IPU_ISYS_SUBDEV_PROP_TGT_SINK_FMT,
fmt->pad, fmt->which);
}
int __ipu_isys_subdev_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct ipu_isys_subdev *asd = to_ipu_isys_subdev(sd);
struct v4l2_mbus_framefmt *ffmt =
- __ipu_isys_get_ffmt(sd, cfg, fmt->pad, fmt->which);
+ __ipu_isys_get_ffmt(sd, sd_state, fmt->pad, fmt->which);
u32 code = asd->supported_codes[fmt->pad][0];
unsigned int i;
@@ -381,7 +374,7 @@ int __ipu_isys_subdev_set_ffmt(struct v4l2_subdev *sd,
fmt->format.code = code;
- asd->set_ffmt(sd, cfg, fmt);
+ asd->set_ffmt(sd, sd_state, fmt);
fmt->format = *ffmt;
@@ -389,27 +382,27 @@ int __ipu_isys_subdev_set_ffmt(struct v4l2_subdev *sd,
}
int ipu_isys_subdev_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct ipu_isys_subdev *asd = to_ipu_isys_subdev(sd);
int rval;
mutex_lock(&asd->mutex);
- rval = __ipu_isys_subdev_set_ffmt(sd, cfg, fmt);
+ rval = __ipu_isys_subdev_set_ffmt(sd, sd_state, fmt);
mutex_unlock(&asd->mutex);
return rval;
}
int ipu_isys_subdev_get_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct ipu_isys_subdev *asd = to_ipu_isys_subdev(sd);
mutex_lock(&asd->mutex);
- fmt->format = *__ipu_isys_get_ffmt(sd, cfg, fmt->pad,
+ fmt->format = *__ipu_isys_get_ffmt(sd, sd_state, fmt->pad,
fmt->which);
mutex_unlock(&asd->mutex);
@@ -417,7 +410,7 @@ int ipu_isys_subdev_get_ffmt(struct v4l2_subdev *sd,
}
int ipu_isys_subdev_set_sel(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
struct ipu_isys_subdev *asd = to_ipu_isys_subdev(sd);
@@ -432,7 +425,7 @@ int ipu_isys_subdev_set_sel(struct v4l2_subdev *sd,
case V4L2_SEL_TGT_CROP:
if (pad->flags & MEDIA_PAD_FL_SINK) {
struct v4l2_mbus_framefmt *ffmt =
- __ipu_isys_get_ffmt(sd, cfg, sel->pad,
+ __ipu_isys_get_ffmt(sd, sd_state, sel->pad,
sel->which);
__r.width = ffmt->width;
@@ -441,7 +434,7 @@ int ipu_isys_subdev_set_sel(struct v4l2_subdev *sd,
tgt = IPU_ISYS_SUBDEV_PROP_TGT_SINK_CROP;
} else {
/* 0 is the sink pad. */
- r = __ipu_isys_get_selection(sd, cfg, sel->target, 0,
+ r = __ipu_isys_get_selection(sd, sd_state, sel->target, 0,
sel->which);
tgt = IPU_ISYS_SUBDEV_PROP_TGT_SOURCE_CROP;
}
@@ -449,11 +442,11 @@ int ipu_isys_subdev_set_sel(struct v4l2_subdev *sd,
break;
case V4L2_SEL_TGT_COMPOSE:
if (pad->flags & MEDIA_PAD_FL_SINK) {
- r = __ipu_isys_get_selection(sd, cfg, V4L2_SEL_TGT_CROP,
+ r = __ipu_isys_get_selection(sd, sd_state, V4L2_SEL_TGT_CROP,
sel->pad, sel->which);
tgt = IPU_ISYS_SUBDEV_PROP_TGT_SINK_COMPOSE;
} else {
- r = __ipu_isys_get_selection(sd, cfg,
+ r = __ipu_isys_get_selection(sd, sd_state,
V4L2_SEL_TGT_COMPOSE, 0,
sel->which);
tgt = IPU_ISYS_SUBDEV_PROP_TGT_SOURCE_COMPOSE;
@@ -465,27 +458,27 @@ int ipu_isys_subdev_set_sel(struct v4l2_subdev *sd,
sel->r.width = clamp(sel->r.width, IPU_ISYS_MIN_WIDTH, r->width);
sel->r.height = clamp(sel->r.height, IPU_ISYS_MIN_HEIGHT, r->height);
- *__ipu_isys_get_selection(sd, cfg, sel->target, sel->pad,
+ *__ipu_isys_get_selection(sd, sd_state, sel->target, sel->pad,
sel->which) = sel->r;
- return ipu_isys_subdev_fmt_propagate(sd, cfg, NULL, &sel->r, tgt,
+ return ipu_isys_subdev_fmt_propagate(sd, sd_state, NULL, &sel->r, tgt,
sel->pad, sel->which);
}
int ipu_isys_subdev_get_sel(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
if (!target_valid(sd, sel->target, sel->pad))
return -EINVAL;
- sel->r = *__ipu_isys_get_selection(sd, cfg, sel->target,
+ sel->r = *__ipu_isys_get_selection(sd, sd_state, sel->target,
sel->pad, sel->which);
return 0;
}
int ipu_isys_subdev_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct ipu_isys_subdev *asd = to_ipu_isys_subdev(sd);
@@ -555,11 +548,11 @@ int ipu_isys_subdev_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
for (i = 0; i < asd->sd.entity.num_pads; i++) {
struct v4l2_mbus_framefmt *try_fmt =
- v4l2_subdev_get_try_format(sd, fh->pad, i);
+ v4l2_subdev_get_try_format(sd, fh->state, i);
struct v4l2_rect *try_crop =
- v4l2_subdev_get_try_crop(sd, fh->pad, i);
+ v4l2_subdev_get_try_crop(sd, fh->state, i);
struct v4l2_rect *try_compose =
- v4l2_subdev_get_try_compose(sd, fh->pad, i);
+ v4l2_subdev_get_try_compose(sd, fh->state, i);
*try_fmt = asd->ffmt[i];
*try_crop = asd->crop[i];
diff --git a/drivers/media/pci/intel/ipu-isys-subdev.h b/drivers/media/pci/intel/ipu-isys-subdev.h
index 35eb9d1d3cb7..053ac094642d 100644
--- a/drivers/media/pci/intel/ipu-isys-subdev.h
+++ b/drivers/media/pci/intel/ipu-isys-subdev.h
@@ -75,7 +75,7 @@ struct ipu_isys_subdev {
struct v4l2_ctrl_handler ctrl_handler;
void (*ctrl_init)(struct v4l2_subdev *sd);
void (*set_ffmt)(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt);
struct {
bool crop;
@@ -90,8 +90,7 @@ struct ipu_isys_subdev {
container_of(__sd, struct ipu_isys_subdev, sd)
struct v4l2_mbus_framefmt *__ipu_isys_get_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config
- *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int pad,
unsigned int which);
@@ -102,37 +101,37 @@ u32 ipu_isys_subdev_code_to_uncompressed(u32 sink_code);
enum ipu_isys_subdev_pixelorder ipu_isys_subdev_get_pixelorder(u32 code);
int ipu_isys_subdev_fmt_propagate(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_mbus_framefmt *ffmt,
struct v4l2_rect *r,
enum isys_subdev_prop_tgt tgt,
unsigned int pad, unsigned int which);
int ipu_isys_subdev_set_ffmt_default(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt);
int __ipu_isys_subdev_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt);
struct v4l2_rect *__ipu_isys_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
unsigned int target,
unsigned int pad,
unsigned int which);
int ipu_isys_subdev_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt);
int ipu_isys_subdev_get_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt);
int ipu_isys_subdev_get_sel(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel);
int ipu_isys_subdev_set_sel(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel);
int ipu_isys_subdev_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum
*code);
int ipu_isys_subdev_link_validate(struct v4l2_subdev *sd,
diff --git a/drivers/media/pci/intel/ipu-isys-tpg.c b/drivers/media/pci/intel/ipu-isys-tpg.c
new file mode 100644
index 000000000000..b77ea5d55881
--- /dev/null
+++ b/drivers/media/pci/intel/ipu-isys-tpg.c
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2013 - 2020 Intel Corporation
+
+#include <linux/device.h>
+#include <linux/module.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+
+#include "ipu.h"
+#include "ipu-bus.h"
+#include "ipu-isys.h"
+#include "ipu-isys-subdev.h"
+#include "ipu-isys-tpg.h"
+#include "ipu-isys-video.h"
+#include "ipu-platform-isys-csi2-reg.h"
+
+static const u32 tpg_supported_codes_pad[] = {
+ MEDIA_BUS_FMT_SBGGR8_1X8,
+ MEDIA_BUS_FMT_SGBRG8_1X8,
+ MEDIA_BUS_FMT_SGRBG8_1X8,
+ MEDIA_BUS_FMT_SRGGB8_1X8,
+ MEDIA_BUS_FMT_SBGGR10_1X10,
+ MEDIA_BUS_FMT_SGBRG10_1X10,
+ MEDIA_BUS_FMT_SGRBG10_1X10,
+ MEDIA_BUS_FMT_SRGGB10_1X10,
+ 0,
+};
+
+static const u32 *tpg_supported_codes[] = {
+ tpg_supported_codes_pad,
+};
+
+static struct v4l2_subdev_internal_ops tpg_sd_internal_ops = {
+ .open = ipu_isys_subdev_open,
+ .close = ipu_isys_subdev_close,
+};
+
+static const struct v4l2_subdev_video_ops tpg_sd_video_ops = {
+ .s_stream = tpg_set_stream,
+};
+
+static int ipu_isys_tpg_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct ipu_isys_tpg *tpg = container_of(container_of(ctrl->handler,
+ struct
+ ipu_isys_subdev,
+ ctrl_handler),
+ struct ipu_isys_tpg, asd);
+
+ switch (ctrl->id) {
+ case V4L2_CID_HBLANK:
+ writel(ctrl->val, tpg->base + MIPI_GEN_REG_SYNG_HBLANK_CYC);
+ break;
+ case V4L2_CID_VBLANK:
+ writel(ctrl->val, tpg->base + MIPI_GEN_REG_SYNG_VBLANK_CYC);
+ break;
+ case V4L2_CID_TEST_PATTERN:
+ writel(ctrl->val, tpg->base + MIPI_GEN_REG_TPG_MODE);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops ipu_isys_tpg_ctrl_ops = {
+ .s_ctrl = ipu_isys_tpg_s_ctrl,
+};
+
+static s64 ipu_isys_tpg_rate(struct ipu_isys_tpg *tpg, unsigned int bpp)
+{
+ return MIPI_GEN_PPC * IPU_ISYS_FREQ / bpp;
+}
+
+static const char *const tpg_mode_items[] = {
+ "Ramp",
+ "Checkerboard", /* Does not work, disabled. */
+ "Frame Based Colour",
+};
+
+static struct v4l2_ctrl_config tpg_mode = {
+ .ops = &ipu_isys_tpg_ctrl_ops,
+ .id = V4L2_CID_TEST_PATTERN,
+ .name = "Test Pattern",
+ .type = V4L2_CTRL_TYPE_MENU,
+ .min = 0,
+ .max = ARRAY_SIZE(tpg_mode_items) - 1,
+ .def = 0,
+ .menu_skip_mask = 0x2,
+ .qmenu = tpg_mode_items,
+};
+
+static const struct v4l2_ctrl_config csi2_header_cfg = {
+ .id = V4L2_CID_IPU_STORE_CSI2_HEADER,
+ .name = "Store CSI-2 Headers",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 1,
+};
+
+static void ipu_isys_tpg_init_controls(struct v4l2_subdev *sd)
+{
+ struct ipu_isys_tpg *tpg = to_ipu_isys_tpg(sd);
+ int hblank;
+ u64 default_pixel_rate;
+
+ hblank = 1024;
+
+ tpg->hblank = v4l2_ctrl_new_std(&tpg->asd.ctrl_handler,
+ &ipu_isys_tpg_ctrl_ops,
+ V4L2_CID_HBLANK, 8, 65535, 1, hblank);
+
+ tpg->vblank = v4l2_ctrl_new_std(&tpg->asd.ctrl_handler,
+ &ipu_isys_tpg_ctrl_ops,
+ V4L2_CID_VBLANK, 8, 65535, 1, 1024);
+
+ default_pixel_rate = ipu_isys_tpg_rate(tpg, 8);
+ tpg->pixel_rate = v4l2_ctrl_new_std(&tpg->asd.ctrl_handler,
+ &ipu_isys_tpg_ctrl_ops,
+ V4L2_CID_PIXEL_RATE,
+ default_pixel_rate,
+ default_pixel_rate,
+ 1, default_pixel_rate);
+ if (tpg->pixel_rate) {
+ tpg->pixel_rate->cur.val = default_pixel_rate;
+ tpg->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ }
+
+ v4l2_ctrl_new_custom(&tpg->asd.ctrl_handler, &tpg_mode, NULL);
+ tpg->store_csi2_header =
+ v4l2_ctrl_new_custom(&tpg->asd.ctrl_handler,
+ &csi2_header_cfg, NULL);
+}
+
+static void tpg_set_ffmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ fmt->format.field = V4L2_FIELD_NONE;
+ *__ipu_isys_get_ffmt(sd, sd_state, fmt->pad, fmt->which) = fmt->format;
+}
+
+static int ipu_isys_tpg_set_ffmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct ipu_isys_tpg *tpg = to_ipu_isys_tpg(sd);
+ __u32 code = tpg->asd.ffmt[TPG_PAD_SOURCE].code;
+ unsigned int bpp = ipu_isys_mbus_code_to_bpp(code);
+ s64 tpg_rate = ipu_isys_tpg_rate(tpg, bpp);
+ int rval;
+
+ mutex_lock(&tpg->asd.mutex);
+ rval = __ipu_isys_subdev_set_ffmt(sd, sd_state, fmt);
+ mutex_unlock(&tpg->asd.mutex);
+
+ if (rval || fmt->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return rval;
+
+ v4l2_ctrl_s_ctrl_int64(tpg->pixel_rate, tpg_rate);
+
+ return 0;
+}
+
+static const struct ipu_isys_pixelformat *
+ipu_isys_tpg_try_fmt(struct ipu_isys_video *av,
+ struct v4l2_pix_format_mplane *mpix)
+{
+ struct media_link *link = list_first_entry(&av->vdev.entity.links,
+ struct media_link, list);
+ struct v4l2_subdev *sd =
+ media_entity_to_v4l2_subdev(link->source->entity);
+ struct ipu_isys_tpg *tpg;
+
+ if (!sd)
+ return NULL;
+
+ tpg = to_ipu_isys_tpg(sd);
+
+ return ipu_isys_video_try_fmt_vid_mplane(av, mpix,
+ v4l2_ctrl_g_ctrl(tpg->store_csi2_header));
+}
+
+static const struct v4l2_subdev_pad_ops tpg_sd_pad_ops = {
+ .get_fmt = ipu_isys_subdev_get_ffmt,
+ .set_fmt = ipu_isys_tpg_set_ffmt,
+ .enum_mbus_code = ipu_isys_subdev_enum_mbus_code,
+};
+
+static int subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ switch (sub->type) {
+#ifdef IPU_TPG_FRAME_SYNC
+ case V4L2_EVENT_FRAME_SYNC:
+ return v4l2_event_subscribe(fh, sub, 10, NULL);
+#endif
+ case V4L2_EVENT_CTRL:
+ return v4l2_ctrl_subscribe_event(fh, sub);
+ default:
+ return -EINVAL;
+ }
+};
+
+/* V4L2 subdev core operations */
+static const struct v4l2_subdev_core_ops tpg_sd_core_ops = {
+ .subscribe_event = subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static struct v4l2_subdev_ops tpg_sd_ops = {
+ .core = &tpg_sd_core_ops,
+ .video = &tpg_sd_video_ops,
+ .pad = &tpg_sd_pad_ops,
+};
+
+static struct media_entity_operations tpg_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+void ipu_isys_tpg_cleanup(struct ipu_isys_tpg *tpg)
+{
+ v4l2_device_unregister_subdev(&tpg->asd.sd);
+ ipu_isys_subdev_cleanup(&tpg->asd);
+ ipu_isys_video_cleanup(&tpg->av);
+}
+
+int ipu_isys_tpg_init(struct ipu_isys_tpg *tpg,
+ struct ipu_isys *isys,
+ void __iomem *base, void __iomem *sel,
+ unsigned int index)
+{
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .pad = TPG_PAD_SOURCE,
+ .format = {
+ .width = 4096,
+ .height = 3072,
+ },
+ };
+ int rval;
+
+ tpg->isys = isys;
+ tpg->base = base;
+ tpg->sel = sel;
+ tpg->index = index;
+
+ tpg->asd.sd.entity.ops = &tpg_entity_ops;
+ tpg->asd.ctrl_init = ipu_isys_tpg_init_controls;
+ tpg->asd.isys = isys;
+
+ rval = ipu_isys_subdev_init(&tpg->asd, &tpg_sd_ops, 5,
+ NR_OF_TPG_PADS,
+ NR_OF_TPG_SOURCE_PADS,
+ NR_OF_TPG_SINK_PADS,
+ V4L2_SUBDEV_FL_HAS_EVENTS);
+ if (rval)
+ return rval;
+
+ tpg->asd.sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ tpg->asd.pad[TPG_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+ tpg->asd.source = IPU_FW_ISYS_STREAM_SRC_MIPIGEN_PORT0 + index;
+ tpg->asd.supported_codes = tpg_supported_codes;
+ tpg->asd.set_ffmt = tpg_set_ffmt;
+ ipu_isys_subdev_set_ffmt(&tpg->asd.sd, NULL, &fmt);
+
+ tpg->asd.sd.internal_ops = &tpg_sd_internal_ops;
+ snprintf(tpg->asd.sd.name, sizeof(tpg->asd.sd.name),
+ IPU_ISYS_ENTITY_PREFIX " TPG %u", index);
+ v4l2_set_subdevdata(&tpg->asd.sd, &tpg->asd);
+ rval = v4l2_device_register_subdev(&isys->v4l2_dev, &tpg->asd.sd);
+ if (rval) {
+ dev_info(&isys->adev->dev, "can't register v4l2 subdev\n");
+ goto fail;
+ }
+
+ snprintf(tpg->av.vdev.name, sizeof(tpg->av.vdev.name),
+ IPU_ISYS_ENTITY_PREFIX " TPG %u capture", index);
+ tpg->av.isys = isys;
+ tpg->av.aq.css_pin_type = IPU_FW_ISYS_PIN_TYPE_MIPI;
+ tpg->av.pfmts = ipu_isys_pfmts_packed;
+ tpg->av.try_fmt_vid_mplane = ipu_isys_tpg_try_fmt;
+ tpg->av.prepare_fw_stream =
+ ipu_isys_prepare_fw_cfg_default;
+ tpg->av.packed = true;
+ tpg->av.line_header_length = IPU_ISYS_CSI2_LONG_PACKET_HEADER_SIZE;
+ tpg->av.line_footer_length = IPU_ISYS_CSI2_LONG_PACKET_FOOTER_SIZE;
+ tpg->av.aq.buf_prepare = ipu_isys_buf_prepare;
+ tpg->av.aq.fill_frame_buff_set_pin =
+ ipu_isys_buffer_to_fw_frame_buff_pin;
+ tpg->av.aq.link_fmt_validate = ipu_isys_link_fmt_validate;
+ tpg->av.aq.vbq.buf_struct_size = sizeof(struct ipu_isys_video_buffer);
+
+ rval = ipu_isys_video_init(&tpg->av, &tpg->asd.sd.entity,
+ TPG_PAD_SOURCE, MEDIA_PAD_FL_SINK, 0);
+ if (rval) {
+ dev_info(&isys->adev->dev, "can't init video node\n");
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ ipu_isys_tpg_cleanup(tpg);
+
+ return rval;
+}
diff --git a/drivers/media/pci/intel/ipu-isys-tpg.h b/drivers/media/pci/intel/ipu-isys-tpg.h
new file mode 100644
index 000000000000..332f087ed774
--- /dev/null
+++ b/drivers/media/pci/intel/ipu-isys-tpg.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2013 - 2020 Intel Corporation */
+
+#ifndef IPU_ISYS_TPG_H
+#define IPU_ISYS_TPG_H
+
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+#include "ipu-isys-subdev.h"
+#include "ipu-isys-video.h"
+#include "ipu-isys-queue.h"
+
+struct ipu_isys_tpg_pdata;
+struct ipu_isys;
+
+#define TPG_PAD_SOURCE 0
+#define NR_OF_TPG_PADS 1
+#define NR_OF_TPG_SOURCE_PADS 1
+#define NR_OF_TPG_SINK_PADS 0
+#define NR_OF_TPG_STREAMS 1
+
+/*
+ * PPC is 4 pixels for clock for RAW8, RAW10 and RAW12.
+ * Source: FW validation test code.
+ */
+#define MIPI_GEN_PPC 4
+
+#define MIPI_GEN_REG_COM_ENABLE 0x0
+#define MIPI_GEN_REG_COM_DTYPE 0x4
+/* RAW8, RAW10 or RAW12 */
+#define MIPI_GEN_COM_DTYPE_RAW(n) (((n) - 8) / 2)
+#define MIPI_GEN_REG_COM_VTYPE 0x8
+#define MIPI_GEN_REG_COM_VCHAN 0xc
+#define MIPI_GEN_REG_COM_WCOUNT 0x10
+#define MIPI_GEN_REG_PRBS_RSTVAL0 0x14
+#define MIPI_GEN_REG_PRBS_RSTVAL1 0x18
+#define MIPI_GEN_REG_SYNG_FREE_RUN 0x1c
+#define MIPI_GEN_REG_SYNG_PAUSE 0x20
+#define MIPI_GEN_REG_SYNG_NOF_FRAMES 0x24
+#define MIPI_GEN_REG_SYNG_NOF_PIXELS 0x28
+#define MIPI_GEN_REG_SYNG_NOF_LINES 0x2c
+#define MIPI_GEN_REG_SYNG_HBLANK_CYC 0x30
+#define MIPI_GEN_REG_SYNG_VBLANK_CYC 0x34
+#define MIPI_GEN_REG_SYNG_STAT_HCNT 0x38
+#define MIPI_GEN_REG_SYNG_STAT_VCNT 0x3c
+#define MIPI_GEN_REG_SYNG_STAT_FCNT 0x40
+#define MIPI_GEN_REG_SYNG_STAT_DONE 0x44
+#define MIPI_GEN_REG_TPG_MODE 0x48
+#define MIPI_GEN_REG_TPG_HCNT_MASK 0x4c
+#define MIPI_GEN_REG_TPG_VCNT_MASK 0x50
+#define MIPI_GEN_REG_TPG_XYCNT_MASK 0x54
+#define MIPI_GEN_REG_TPG_HCNT_DELTA 0x58
+#define MIPI_GEN_REG_TPG_VCNT_DELTA 0x5c
+#define MIPI_GEN_REG_TPG_R1 0x60
+#define MIPI_GEN_REG_TPG_G1 0x64
+#define MIPI_GEN_REG_TPG_B1 0x68
+#define MIPI_GEN_REG_TPG_R2 0x6c
+#define MIPI_GEN_REG_TPG_G2 0x70
+#define MIPI_GEN_REG_TPG_B2 0x74
+
+/*
+ * struct ipu_isys_tpg
+ *
+ * @nlanes: number of lanes in the receiver
+ */
+struct ipu_isys_tpg {
+ struct ipu_isys_tpg_pdata *pdata;
+ struct ipu_isys *isys;
+ struct ipu_isys_subdev asd;
+ struct ipu_isys_video av;
+
+ void __iomem *base;
+ void __iomem *sel;
+ unsigned int index;
+ int streaming;
+
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *vblank;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *store_csi2_header;
+};
+
+#define to_ipu_isys_tpg(sd) \
+ container_of(to_ipu_isys_subdev(sd), \
+ struct ipu_isys_tpg, asd)
+#ifdef IPU_TPG_FRAME_SYNC
+void ipu_isys_tpg_sof_event(struct ipu_isys_tpg *tpg);
+void ipu_isys_tpg_eof_event(struct ipu_isys_tpg *tpg);
+#endif
+int ipu_isys_tpg_init(struct ipu_isys_tpg *tpg,
+ struct ipu_isys *isys,
+ void __iomem *base, void __iomem *sel,
+ unsigned int index);
+void ipu_isys_tpg_cleanup(struct ipu_isys_tpg *tpg);
+int tpg_set_stream(struct v4l2_subdev *sd, int enable);
+
+#endif /* IPU_ISYS_TPG_H */
diff --git a/drivers/media/pci/intel/ipu-isys.c b/drivers/media/pci/intel/ipu-isys.c
index d7c493228c69..69df93bf7b02 100644
--- a/drivers/media/pci/intel/ipu-isys.c
+++ b/drivers/media/pci/intel/ipu-isys.c
@@ -946,7 +946,6 @@ void ipu_put_fw_mgs_buf(struct ipu_isys *isys, u64 data)
list_move(&msg->head, &isys->framebuflist);
spin_unlock_irqrestore(&isys->listlock, flags);
}
-EXPORT_SYMBOL_GPL(ipu_put_fw_mgs_buf);
static int isys_probe(struct ipu_bus_device *adev)
{
@@ -1314,34 +1313,6 @@ int isys_isr_one(struct ipu_bus_device *adev)
return 0;
}
-static void isys_isr_poll(struct ipu_bus_device *adev)
-{
- struct ipu_isys *isys = ipu_bus_get_drvdata(adev);
-
- if (!isys->fwcom) {
- dev_dbg(&isys->adev->dev,
- "got interrupt but device not configured yet\n");
- return;
- }
-
- mutex_lock(&isys->mutex);
- isys_isr(adev);
- mutex_unlock(&isys->mutex);
-}
-
-int ipu_isys_isr_run(void *ptr)
-{
- struct ipu_isys *isys = ptr;
-
- while (!kthread_should_stop()) {
- usleep_range(500, 1000);
- if (isys->stream_opened)
- isys_isr_poll(isys->adev);
- }
-
- return 0;
-}
-
static struct ipu_bus_driver isys_driver = {
.probe = isys_probe,
.remove = isys_remove,
@@ -1359,7 +1330,8 @@ module_ipu_bus_driver(isys_driver);
static const struct pci_device_id ipu_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6_PCI_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6SE_PCI_ID)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6EP_PCI_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6EP_ADL_P_PCI_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6EP_ADL_N_PCI_ID)},
{0,}
};
MODULE_DEVICE_TABLE(pci, ipu_pci_tbl);
diff --git a/drivers/media/pci/intel/ipu-isys.h b/drivers/media/pci/intel/ipu-isys.h
index 57bc4b55bf26..8b1228febdf6 100644
--- a/drivers/media/pci/intel/ipu-isys.h
+++ b/drivers/media/pci/intel/ipu-isys.h
@@ -219,7 +219,6 @@ extern const struct v4l2_ioctl_ops ipu_isys_ioctl_ops;
void isys_setup_hw(struct ipu_isys *isys);
int isys_isr_one(struct ipu_bus_device *adev);
-int ipu_isys_isr_run(void *ptr);
irqreturn_t isys_isr(struct ipu_bus_device *adev);
#ifdef IPU_ISYS_GPC
int ipu_isys_gpc_init_debugfs(struct ipu_isys *isys);
diff --git a/drivers/media/pci/intel/ipu-mmu.c b/drivers/media/pci/intel/ipu-mmu.c
index ad84c7b63441..7d38529820b1 100644
--- a/drivers/media/pci/intel/ipu-mmu.c
+++ b/drivers/media/pci/intel/ipu-mmu.c
@@ -785,7 +785,7 @@ static void ipu_mmu_destroy(struct ipu_mmu *mmu)
}
free_dummy_page(mmu_info);
- dma_unmap_single(mmu_info->dev, mmu_info->l1_pt_dma,
+ dma_unmap_single(mmu_info->dev, mmu_info->l1_pt_dma << ISP_PADDR_SHIFT,
PAGE_SIZE, DMA_BIDIRECTIONAL);
free_page((unsigned long)mmu_info->dummy_l2_pt);
free_page((unsigned long)mmu_info->l1_pt);
@@ -840,7 +840,6 @@ struct ipu_mmu *ipu_mmu_init(struct device *dev,
return mmu;
}
-EXPORT_SYMBOL(ipu_mmu_init);
void ipu_mmu_cleanup(struct ipu_mmu *mmu)
{
@@ -852,7 +851,6 @@ void ipu_mmu_cleanup(struct ipu_mmu *mmu)
put_iova_domain(&dmap->iovad);
kfree(dmap);
}
-EXPORT_SYMBOL(ipu_mmu_cleanup);
MODULE_AUTHOR("Sakari Ailus <sakari.ailus at linux.intel.com>");
MODULE_AUTHOR("Samu Onkalo <samu.onkalo at intel.com>");
diff --git a/drivers/media/pci/intel/ipu-psys-compat32.c b/drivers/media/pci/intel/ipu-psys-compat32.c
index ba13127d946e..763ebc2c1a9f 100644
--- a/drivers/media/pci/intel/ipu-psys-compat32.c
+++ b/drivers/media/pci/intel/ipu-psys-compat32.c
@@ -223,4 +223,3 @@ long ipu_psys_compat_ioctl32(struct file *file, unsigned int cmd,
}
return err;
}
-EXPORT_SYMBOL_GPL(ipu_psys_compat_ioctl32);
diff --git a/drivers/media/pci/intel/ipu-psys.c b/drivers/media/pci/intel/ipu-psys.c
index d0c71c86928f..0774ebc8bc9c 100644
--- a/drivers/media/pci/intel/ipu-psys.c
+++ b/drivers/media/pci/intel/ipu-psys.c
@@ -1340,7 +1340,6 @@ static int ipu_psys_probe(struct ipu_bus_device *adev)
INIT_LIST_HEAD(&psys->fhs);
INIT_LIST_HEAD(&psys->pgs);
INIT_LIST_HEAD(&psys->started_kcmds_list);
- INIT_WORK(&psys->watchdog_work, ipu_psys_watchdog_work);
init_waitqueue_head(&psys->sched_cmd_wq);
atomic_set(&psys->wakeup_count, 0);
@@ -1360,18 +1359,11 @@ static int ipu_psys_probe(struct ipu_bus_device *adev)
ipu_bus_set_drvdata(adev, psys);
- rval = ipu_psys_resource_pool_init(&psys->resource_pool_started);
- if (rval < 0) {
- dev_err(&psys->dev,
- "unable to alloc process group resources\n");
- goto out_mutex_destroy;
- }
-
rval = ipu_psys_resource_pool_init(&psys->resource_pool_running);
if (rval < 0) {
dev_err(&psys->dev,
"unable to alloc process group resources\n");
- goto out_resources_started_free;
+ goto out_mutex_destroy;
}
ipu6_psys_hw_res_variant_init();
@@ -1459,8 +1451,6 @@ static int ipu_psys_probe(struct ipu_bus_device *adev)
}
ipu_psys_resource_pool_cleanup(&psys->resource_pool_running);
-out_resources_started_free:
- ipu_psys_resource_pool_cleanup(&psys->resource_pool_started);
out_mutex_destroy:
mutex_destroy(&psys->mutex);
cdev_del(&psys->cdev);
@@ -1514,7 +1504,6 @@ static void ipu_psys_remove(struct ipu_bus_device *adev)
ipu_trace_uninit(&adev->dev);
- ipu_psys_resource_pool_cleanup(&psys->resource_pool_started);
ipu_psys_resource_pool_cleanup(&psys->resource_pool_running);
device_unregister(&psys->dev);
@@ -1608,7 +1597,8 @@ static void __exit ipu_psys_exit(void)
static const struct pci_device_id ipu_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6_PCI_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6SE_PCI_ID)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6EP_PCI_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6EP_ADL_P_PCI_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6EP_ADL_N_PCI_ID)},
{0,}
};
MODULE_DEVICE_TABLE(pci, ipu_pci_tbl);
diff --git a/drivers/media/pci/intel/ipu-psys.h b/drivers/media/pci/intel/ipu-psys.h
index b5ddf50791d7..80d70f2ef3ce 100644
--- a/drivers/media/pci/intel/ipu-psys.h
+++ b/drivers/media/pci/intel/ipu-psys.h
@@ -60,6 +60,8 @@ struct ipu_psys_resource_pool {
struct ipu_resource ext_memory[32];
struct ipu_resource dfms[16];
DECLARE_BITMAP(cmd_queues, 32);
+ /* Protects cmd_queues bitmap */
+ spinlock_t queues_lock;
};
/*
@@ -95,7 +97,6 @@ struct ipu_psys {
struct ia_css_syscom_config *syscom_config;
struct ia_css_psys_server_init *server_init;
struct task_struct *sched_cmd_thread;
- struct work_struct watchdog_work;
wait_queue_head_t sched_cmd_wq;
atomic_t wakeup_count; /* Psys schedule thread wakeup count */
#ifdef CONFIG_DEBUG_FS
@@ -104,7 +105,6 @@ struct ipu_psys {
/* Resources needed to be managed for process groups */
struct ipu_psys_resource_pool resource_pool_running;
- struct ipu_psys_resource_pool resource_pool_started;
const struct firmware *fw;
struct sg_table fw_sgt;
@@ -198,7 +198,6 @@ void ipu_psys_subdomains_power(struct ipu_psys *psys, bool on);
void ipu_psys_handle_events(struct ipu_psys *psys);
int ipu_psys_kcmd_new(struct ipu_psys_command *cmd, struct ipu_psys_fh *fh);
void ipu_psys_run_next(struct ipu_psys *psys);
-void ipu_psys_watchdog_work(struct work_struct *work);
struct ipu_psys_pg *__get_pg_buf(struct ipu_psys *psys, size_t pg_size);
struct ipu_psys_kbuffer *
ipu_psys_lookup_kbuffer(struct ipu_psys_fh *fh, int fd);
diff --git a/drivers/media/pci/intel/ipu.c b/drivers/media/pci/intel/ipu.c
index f7826d07ea54..691907561e9a 100644
--- a/drivers/media/pci/intel/ipu.c
+++ b/drivers/media/pci/intel/ipu.c
@@ -415,7 +415,8 @@ static int ipu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ipu_ver = IPU_VER_6SE;
isp->cpd_fw_name = IPU6SE_FIRMWARE_NAME;
break;
- case IPU6EP_PCI_ID:
+ case IPU6EP_ADL_P_PCI_ID:
+ case IPU6EP_ADL_N_PCI_ID:
ipu_ver = IPU_VER_6EP;
isp->cpd_fw_name = IPU6EP_FIRMWARE_NAME;
break;
@@ -750,7 +751,8 @@ static const struct dev_pm_ops ipu_pm_ops = {
static const struct pci_device_id ipu_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6_PCI_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6SE_PCI_ID)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6EP_PCI_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6EP_ADL_P_PCI_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, IPU6EP_ADL_N_PCI_ID)},
{0,}
};
MODULE_DEVICE_TABLE(pci, ipu_pci_tbl);
diff --git a/drivers/media/pci/intel/ipu.h b/drivers/media/pci/intel/ipu.h
index 2b8758ccab9b..4ef08954dcea 100644
--- a/drivers/media/pci/intel/ipu.h
+++ b/drivers/media/pci/intel/ipu.h
@@ -16,7 +16,8 @@
#define IPU6_PCI_ID 0x9a19
#define IPU6SE_PCI_ID 0x4e19
-#define IPU6EP_PCI_ID 0x465d
+#define IPU6EP_ADL_P_PCI_ID 0x465d
+#define IPU6EP_ADL_N_PCI_ID 0x462e
enum ipu_version {
IPU_VER_INVALID = 0,
diff --git a/drivers/media/pci/intel/ipu6/ipu-resources.c b/drivers/media/pci/intel/ipu6/ipu-resources.c
index b246fc037890..dfe4fde7e83f 100644
--- a/drivers/media/pci/intel/ipu6/ipu-resources.c
+++ b/drivers/media/pci/intel/ipu6/ipu-resources.c
@@ -141,15 +141,14 @@ static void ipu_resource_cleanup(struct ipu_resource *res)
}
/********** IPU PSYS-specific resource handling **********/
-static DEFINE_SPINLOCK(cq_bitmap_lock);
-int ipu_psys_resource_pool_init(struct ipu_psys_resource_pool
- *pool)
+int ipu_psys_resource_pool_init(struct ipu_psys_resource_pool *pool)
{
int i, j, k, ret;
const struct ipu_fw_resource_definitions *res_defs;
res_defs = get_res();
+ spin_lock_init(&pool->queues_lock);
pool->cells = 0;
for (i = 0; i < res_defs->num_dev_channels; i++) {
@@ -172,14 +171,14 @@ int ipu_psys_resource_pool_init(struct ipu_psys_resource_pool
goto dfm_error;
}
- spin_lock(&cq_bitmap_lock);
+ spin_lock(&pool->queues_lock);
if (ipu_ver == IPU_VER_6SE)
bitmap_zero(pool->cmd_queues,
IPU6SE_FW_PSYS_N_PSYS_CMD_QUEUE_ID);
else
bitmap_zero(pool->cmd_queues,
IPU6_FW_PSYS_N_PSYS_CMD_QUEUE_ID);
- spin_unlock(&cq_bitmap_lock);
+ spin_unlock(&pool->queues_lock);
return 0;
@@ -272,17 +271,6 @@ static int __alloc_one_resrc(const struct device *dev,
return 0;
}
-static inline unsigned int bit_count(unsigned int n)
-{
- unsigned int counter = 0;
-
- while (n) {
- counter++;
- n &= (n - 1);
- }
- return counter;
-}
-
static int ipu_psys_allocate_one_dfm(const struct device *dev,
struct ipu_fw_psys_process *process,
struct ipu_resource *resource,
@@ -316,7 +304,7 @@ static int ipu_psys_allocate_one_dfm(const struct device *dev,
}
*resource->bitmap |= dfm_bitmap_req;
} else {
- unsigned int n = bit_count(dfm_bitmap_req);
+ unsigned int n = hweight32(dfm_bitmap_req);
p = bitmap_find_next_zero_area(resource->bitmap,
resource->elements, 0, n, 0);
@@ -398,17 +386,17 @@ int ipu_psys_allocate_cmd_queue_resource(struct ipu_psys_resource_pool *pool)
start = IPU6SE_FW_PSYS_CMD_QUEUE_PPG0_COMMAND_ID;
}
- spin_lock(&cq_bitmap_lock);
+ spin_lock(&pool->queues_lock);
/* find available cmd queue from ppg0_cmd_id */
p = bitmap_find_next_zero_area(pool->cmd_queues, size, start, 1, 0);
if (p >= size) {
- spin_unlock(&cq_bitmap_lock);
+ spin_unlock(&pool->queues_lock);
return -ENOSPC;
}
bitmap_set(pool->cmd_queues, p, 1);
- spin_unlock(&cq_bitmap_lock);
+ spin_unlock(&pool->queues_lock);
return p;
}
@@ -416,9 +404,9 @@ int ipu_psys_allocate_cmd_queue_resource(struct ipu_psys_resource_pool *pool)
void ipu_psys_free_cmd_queue_resource(struct ipu_psys_resource_pool *pool,
u8 queue_id)
{
- spin_lock(&cq_bitmap_lock);
+ spin_lock(&pool->queues_lock);
bitmap_clear(pool->cmd_queues, queue_id, 1);
- spin_unlock(&cq_bitmap_lock);
+ spin_unlock(&pool->queues_lock);
}
int ipu_psys_try_allocate_resources(struct device *dev,
diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-resources.c b/drivers/media/pci/intel/ipu6/ipu6-fw-resources.c
index 9569a146e739..338e90d8f29b 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-fw-resources.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-resources.c
@@ -13,7 +13,7 @@
/*
* Cell types by cell IDs
*/
-const u8 ipu6_fw_psys_cell_types[IPU6_FW_PSYS_N_CELL_ID] = {
+static const u8 ipu6_fw_psys_cell_types[IPU6_FW_PSYS_N_CELL_ID] = {
IPU6_FW_PSYS_SP_CTRL_TYPE_ID,
IPU6_FW_PSYS_VP_TYPE_ID,
IPU6_FW_PSYS_ACC_PSA_TYPE_ID,
@@ -48,7 +48,7 @@ const u8 ipu6_fw_psys_cell_types[IPU6_FW_PSYS_N_CELL_ID] = {
IPU6_FW_PSYS_TNR_TYPE_ID,
};
-const u16 ipu6_fw_num_dev_channels[IPU6_FW_PSYS_N_DEV_CHN_ID] = {
+static const u16 ipu6_fw_num_dev_channels[IPU6_FW_PSYS_N_DEV_CHN_ID] = {
IPU6_FW_PSYS_DEV_CHN_DMA_EXT0_MAX_SIZE,
IPU6_FW_PSYS_DEV_CHN_DMA_EXT1_READ_MAX_SIZE,
IPU6_FW_PSYS_DEV_CHN_DMA_EXT1_WRITE_MAX_SIZE,
@@ -56,7 +56,7 @@ const u16 ipu6_fw_num_dev_channels[IPU6_FW_PSYS_N_DEV_CHN_ID] = {
IPU6_FW_PSYS_DEV_CHN_DMA_ISA_MAX_SIZE,
};
-const u16 ipu6_fw_psys_mem_size[IPU6_FW_PSYS_N_MEM_ID] = {
+static const u16 ipu6_fw_psys_mem_size[IPU6_FW_PSYS_N_MEM_ID] = {
IPU6_FW_PSYS_VMEM0_MAX_SIZE,
IPU6_FW_PSYS_TRANSFER_VMEM0_MAX_SIZE,
IPU6_FW_PSYS_TRANSFER_VMEM1_MAX_SIZE,
@@ -69,7 +69,7 @@ const u16 ipu6_fw_psys_mem_size[IPU6_FW_PSYS_N_MEM_ID] = {
IPU6_FW_PSYS_PMEM0_MAX_SIZE
};
-const u16 ipu6_fw_psys_dfms[IPU6_FW_PSYS_N_DEV_DFM_ID] = {
+static const u16 ipu6_fw_psys_dfms[IPU6_FW_PSYS_N_DEV_DFM_ID] = {
IPU6_FW_PSYS_DEV_DFM_BB_FULL_PORT_ID_MAX_SIZE,
IPU6_FW_PSYS_DEV_DFM_BB_EMPTY_PORT_ID_MAX_SIZE,
IPU6_FW_PSYS_DEV_DFM_ISL_FULL_PORT_ID_MAX_SIZE,
@@ -78,7 +78,7 @@ const u16 ipu6_fw_psys_dfms[IPU6_FW_PSYS_N_DEV_DFM_ID] = {
IPU6_FW_PSYS_DEV_DFM_LB_EMPTY_PORT_ID_MAX_SIZE,
};
-const u8
+static const u8
ipu6_fw_psys_c_mem[IPU6_FW_PSYS_N_CELL_ID][IPU6_FW_PSYS_N_MEM_TYPE_ID] = {
{
/* IPU6_FW_PSYS_SP0_ID */
@@ -539,6 +539,8 @@ int ipu6_fw_psys_get_program_manifest_by_process(
return 0;
}
+#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) || \
+ (defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
void ipu6_fw_psys_pg_dump(struct ipu_psys *psys,
struct ipu_psys_kcmd *kcmd, const char *note)
{
@@ -593,3 +595,14 @@ void ipu6_fw_psys_pg_dump(struct ipu_psys *psys,
}
}
}
+#else
+void ipu6_fw_psys_pg_dump(struct ipu_psys *psys,
+ struct ipu_psys_kcmd *kcmd, const char *note)
+{
+ if (ipu_ver == IPU_VER_6SE || ipu_ver == IPU_VER_6 ||
+ ipu_ver == IPU_VER_6EP)
+ return;
+
+ WARN(1, "%s ipu_ver:[%u] is unsupported!\n", __func__, ipu_ver);
+}
+#endif
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c b/drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c
index bd8044255efe..a305c0c3e2cf 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c
@@ -173,10 +173,8 @@ int ipu_isys_gpc_init_debugfs(struct ipu_isys *isys)
if (IS_ERR(dir))
goto err;
- file = debugfs_create_bool("enable", 0600, dir,
- &isys_gpcs->gpc[i].enable);
- if (IS_ERR(file))
- goto err;
+ debugfs_create_bool("enable", 0600, dir,
+ &isys_gpcs->gpc[i].enable);
debugfs_create_u32("source", 0600, dir,
&isys_gpcs->gpc[i].source);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c b/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c
index a1165e718def..c26780106c78 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c
@@ -25,7 +25,7 @@ struct phy_reg {
u32 val;
};
-struct phy_reg common_init_regs[] = {
+static const struct phy_reg common_init_regs[] = {
/* for TGL-U, use 0x80000000 */
{0x00000040, 0x80000000},
{0x00000044, 0x00a80880},
@@ -45,7 +45,7 @@ struct phy_reg common_init_regs[] = {
{0x00001944, 0xfa4401e2}
};
-struct phy_reg x1_port0_config_regs[] = {
+static const struct phy_reg x1_port0_config_regs[] = {
{0x00000694, 0xc80060fa},
{0x00000680, 0x3d4f78ea},
{0x00000690, 0x10a0140b},
@@ -69,7 +69,7 @@ struct phy_reg x1_port0_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x1_port1_config_regs[] = {
+static const struct phy_reg x1_port1_config_regs[] = {
{0x00000c94, 0xc80060fa},
{0x00000c80, 0xcf47abea},
{0x00000c90, 0x10a0840b},
@@ -93,7 +93,7 @@ struct phy_reg x1_port1_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x1_port2_config_regs[] = {
+static const struct phy_reg x1_port2_config_regs[] = {
{0x00001294, 0x28f000fa},
{0x00001280, 0x08130cea},
{0x00001290, 0x10a0140b},
@@ -117,7 +117,7 @@ struct phy_reg x1_port2_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x1_port3_config_regs[] = {
+static const struct phy_reg x1_port3_config_regs[] = {
{0x00001894, 0xc80060fa},
{0x00001880, 0x0f90fd6a},
{0x00001890, 0x10a0840b},
@@ -141,7 +141,7 @@ struct phy_reg x1_port3_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x2_port0_config_regs[] = {
+static const struct phy_reg x2_port0_config_regs[] = {
{0x00000694, 0xc80060fa},
{0x00000680, 0x3d4f78ea},
{0x00000690, 0x10a0140b},
@@ -175,7 +175,7 @@ struct phy_reg x2_port0_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x2_port1_config_regs[] = {
+static const struct phy_reg x2_port1_config_regs[] = {
{0x00000c94, 0xc80060fa},
{0x00000c80, 0xcf47abea},
{0x00000c90, 0x10a0840b},
@@ -209,7 +209,7 @@ struct phy_reg x2_port1_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x2_port2_config_regs[] = {
+static const struct phy_reg x2_port2_config_regs[] = {
{0x00001294, 0xc80060fa},
{0x00001280, 0x08130cea},
{0x00001290, 0x10a0140b},
@@ -242,7 +242,7 @@ struct phy_reg x2_port2_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x2_port3_config_regs[] = {
+static const struct phy_reg x2_port3_config_regs[] = {
{0x00001894, 0xc80060fa},
{0x00001880, 0x0f90fd6a},
{0x00001890, 0x10a0840b},
@@ -276,7 +276,7 @@ struct phy_reg x2_port3_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x4_port0_config_regs[] = {
+static const struct phy_reg x4_port0_config_regs[] = {
{0x00000694, 0xc80060fa},
{0x00000680, 0x3d4f78fa},
{0x00000690, 0x10a0140b},
@@ -330,11 +330,11 @@ struct phy_reg x4_port0_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x4_port1_config_regs[] = {
+static const struct phy_reg x4_port1_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x4_port2_config_regs[] = {
+static const struct phy_reg x4_port2_config_regs[] = {
{0x00001294, 0x28f000fa},
{0x00001280, 0x08130cfa},
{0x00001290, 0x10c0140b},
@@ -388,32 +388,32 @@ struct phy_reg x4_port2_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg x4_port3_config_regs[] = {
+static const struct phy_reg x4_port3_config_regs[] = {
{0x00000000, 0x00000000}
};
-struct phy_reg *x1_config_regs[4] = {
+static const struct phy_reg *x1_config_regs[4] = {
x1_port0_config_regs,
x1_port1_config_regs,
x1_port2_config_regs,
x1_port3_config_regs
};
-struct phy_reg *x2_config_regs[4] = {
+static const struct phy_reg *x2_config_regs[4] = {
x2_port0_config_regs,
x2_port1_config_regs,
x2_port2_config_regs,
x2_port3_config_regs
};
-struct phy_reg *x4_config_regs[4] = {
+static const struct phy_reg *x4_config_regs[4] = {
x4_port0_config_regs,
x4_port1_config_regs,
x4_port2_config_regs,
x4_port3_config_regs
};
-struct phy_reg **config_regs[3] = {
+static const struct phy_reg **config_regs[3] = {
x1_config_regs,
x2_config_regs,
x4_config_regs,
@@ -561,7 +561,7 @@ int ipu6_isys_phy_config(struct ipu_isys *isys)
struct ipu_bus_device *adev = to_ipu_bus_device(&isys->adev->dev);
struct ipu_device *isp = adev->isp;
void __iomem *isp_base = isp->base;
- struct phy_reg **phy_config_regs;
+ const struct phy_reg **phy_config_regs;
struct v4l2_async_subdev *asd;
struct sensor_async_subdev *s_asd;
struct ipu_isys_csi2_config cfg;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-ppg.c b/drivers/media/pci/intel/ipu6/ipu6-ppg.c
index c6acf9cb70ef..8f6f413c0393 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-ppg.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-ppg.c
@@ -97,12 +97,14 @@ ipu_psys_create_buffer_set(struct ipu_psys_kcmd *kcmd,
buf_set_size = ipu_fw_psys_ppg_get_buffer_set_size(kcmd);
kbuf_set = __get_buf_set(fh, buf_set_size);
- if (!kbuf_set)
- goto error;
+ if (!kbuf_set) {
+ dev_err(&psys->adev->dev, "failed to create buffer set\n");
+ return NULL;
+ }
kbuf_set->buf_set = ipu_fw_psys_ppg_create_buffer_set(kcmd,
kbuf_set->kaddr,
- 0);
+ 0);
ipu_fw_psys_ppg_buffer_set_vaddress(kbuf_set->buf_set,
kbuf_set->dma_addr);
@@ -111,9 +113,6 @@ ipu_psys_create_buffer_set(struct ipu_psys_kcmd *kcmd,
keb);
return kbuf_set;
-error:
- dev_err(&psys->adev->dev, "failed to create buffer set\n");
- return NULL;
}
int ipu_psys_ppg_get_bufset(struct ipu_psys_kcmd *kcmd,
diff --git a/drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c b/drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c
index 3bf35d245a4f..b6b850a68398 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c
@@ -180,10 +180,8 @@ int ipu_psys_gpc_init_debugfs(struct ipu_psys *psys)
if (IS_ERR(dir))
goto err;
- file = debugfs_create_bool("enable", 0600, dir,
- &psys_gpcs->gpc[idx].enable);
- if (IS_ERR(file))
- goto err;
+ debugfs_create_bool("enable", 0600, dir,
+ &psys_gpcs->gpc[idx].enable);
debugfs_create_u32("source", 0600, dir,
&psys_gpcs->gpc[idx].source);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-psys.c b/drivers/media/pci/intel/ipu6/ipu6-psys.c
index 06560b91948b..294a6f1638e5 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-psys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-psys.c
@@ -20,10 +20,6 @@
#include "ipu-platform-regs.h"
#include "ipu-trace.h"
-#define is_ppg_kcmd(kcmd) (ipu_fw_psys_pg_get_protocol( \
- (struct ipu_psys_kcmd *)kcmd) \
- == IPU_FW_PSYS_PROCESS_GROUP_PROTOCOL_PPG)
-
static bool early_pg_transfer;
module_param(early_pg_transfer, bool, 0664);
MODULE_PARM_DESC(early_pg_transfer,
@@ -501,7 +497,7 @@ int ipu_psys_kcmd_start(struct ipu_psys *psys, struct ipu_psys_kcmd *kcmd)
ret = ipu_fw_psys_pg_start(kcmd);
if (ret) {
dev_err(&psys->adev->dev, "failed to start kcmd!\n");
- goto error;
+ return ret;
}
ipu_fw_psys_pg_dump(psys, kcmd, "run");
@@ -509,29 +505,10 @@ int ipu_psys_kcmd_start(struct ipu_psys *psys, struct ipu_psys_kcmd *kcmd)
ret = ipu_fw_psys_pg_disown(kcmd);
if (ret) {
dev_err(&psys->adev->dev, "failed to start kcmd!\n");
- goto error;
+ return ret;
}
return 0;
-
-error:
- dev_err(&psys->adev->dev, "failed to start process group\n");
- return ret;
-}
-
-void ipu_psys_watchdog_work(struct work_struct *work)
-{
- struct ipu_psys *psys = container_of(work,
- struct ipu_psys, watchdog_work);
- dev_dbg(&psys->adev->dev, "watchdog for ppg not implemented yet!\n");
-}
-
-static void ipu_psys_watchdog(struct timer_list *t)
-{
- struct ipu_psys_kcmd *kcmd = from_timer(kcmd, t, watchdog);
- struct ipu_psys *psys = kcmd->fh->psys;
-
- queue_work(IPU_PSYS_WORK_QUEUE, &psys->watchdog_work);
}
static int ipu_psys_kcmd_send_to_ppg_start(struct ipu_psys_kcmd *kcmd)
@@ -702,14 +679,13 @@ int ipu_psys_kcmd_new(struct ipu_psys_command *cmd, struct ipu_psys_fh *fh)
goto error;
}
- if (!is_ppg_kcmd(kcmd)) {
+ if (ipu_fw_psys_pg_get_protocol(kcmd) !=
+ IPU_FW_PSYS_PROCESS_GROUP_PROTOCOL_PPG) {
dev_err(&psys->adev->dev, "No support legacy pg now\n");
ret = -EINVAL;
goto error;
}
- timer_setup(&kcmd->watchdog, ipu_psys_watchdog, 0);
-
if (cmd->min_psys_freq) {
kcmd->constraint.min_freq = cmd->min_psys_freq;
ipu_buttress_add_psys_constraint(psys->adev->isp,
diff --git a/drivers/media/pci/intel/ipu6/ipu6ep-fw-resources.c b/drivers/media/pci/intel/ipu6/ipu6ep-fw-resources.c
index ca2ab3967e5c..7b1ee7c6dc4e 100644
--- a/drivers/media/pci/intel/ipu6/ipu6ep-fw-resources.c
+++ b/drivers/media/pci/intel/ipu6/ipu6ep-fw-resources.c
@@ -14,7 +14,7 @@
/*
* Cell types by cell IDs
*/
-const u8 ipu6ep_fw_psys_cell_types[IPU6EP_FW_PSYS_N_CELL_ID] = {
+static const u8 ipu6ep_fw_psys_cell_types[IPU6EP_FW_PSYS_N_CELL_ID] = {
IPU6_FW_PSYS_SP_CTRL_TYPE_ID,
IPU6_FW_PSYS_VP_TYPE_ID,
IPU6_FW_PSYS_ACC_PSA_TYPE_ID,
@@ -46,7 +46,7 @@ const u8 ipu6ep_fw_psys_cell_types[IPU6EP_FW_PSYS_N_CELL_ID] = {
IPU6_FW_PSYS_TNR_TYPE_ID,
};
-const u16 ipu6ep_fw_num_dev_channels[IPU6_FW_PSYS_N_DEV_CHN_ID] = {
+static const u16 ipu6ep_fw_num_dev_channels[IPU6_FW_PSYS_N_DEV_CHN_ID] = {
IPU6_FW_PSYS_DEV_CHN_DMA_EXT0_MAX_SIZE,
IPU6_FW_PSYS_DEV_CHN_DMA_EXT1_READ_MAX_SIZE,
IPU6_FW_PSYS_DEV_CHN_DMA_EXT1_WRITE_MAX_SIZE,
@@ -54,7 +54,7 @@ const u16 ipu6ep_fw_num_dev_channels[IPU6_FW_PSYS_N_DEV_CHN_ID] = {
IPU6_FW_PSYS_DEV_CHN_DMA_ISA_MAX_SIZE,
};
-const u16 ipu6ep_fw_psys_mem_size[IPU6_FW_PSYS_N_MEM_ID] = {
+static const u16 ipu6ep_fw_psys_mem_size[IPU6_FW_PSYS_N_MEM_ID] = {
IPU6_FW_PSYS_VMEM0_MAX_SIZE,
IPU6_FW_PSYS_TRANSFER_VMEM0_MAX_SIZE,
IPU6_FW_PSYS_TRANSFER_VMEM1_MAX_SIZE,
@@ -67,7 +67,7 @@ const u16 ipu6ep_fw_psys_mem_size[IPU6_FW_PSYS_N_MEM_ID] = {
IPU6_FW_PSYS_PMEM0_MAX_SIZE
};
-const u16 ipu6ep_fw_psys_dfms[IPU6_FW_PSYS_N_DEV_DFM_ID] = {
+static const u16 ipu6ep_fw_psys_dfms[IPU6_FW_PSYS_N_DEV_DFM_ID] = {
IPU6_FW_PSYS_DEV_DFM_BB_FULL_PORT_ID_MAX_SIZE,
IPU6_FW_PSYS_DEV_DFM_BB_EMPTY_PORT_ID_MAX_SIZE,
IPU6_FW_PSYS_DEV_DFM_ISL_FULL_PORT_ID_MAX_SIZE,
@@ -76,7 +76,7 @@ const u16 ipu6ep_fw_psys_dfms[IPU6_FW_PSYS_N_DEV_DFM_ID] = {
IPU6_FW_PSYS_DEV_DFM_LB_EMPTY_PORT_ID_MAX_SIZE,
};
-const u8
+static const u8
ipu6ep_fw_psys_c_mem[IPU6EP_FW_PSYS_N_CELL_ID][IPU6_FW_PSYS_N_MEM_TYPE_ID] = {
{
/* IPU6_FW_PSYS_SP0_ID */
--
2.33.1
More information about the kernel-team
mailing list