Skip to content

Commit

Permalink
Engineer release on 2022-08-10
Browse files Browse the repository at this point in the history
Signed-off-by: Hao Yao <hao.yao@intel.com>
  • Loading branch information
hao-yao committed Aug 10, 2022
1 parent 3792b52 commit f771bd3
Show file tree
Hide file tree
Showing 41 changed files with 6,392 additions and 244 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
run: |
# there is a dependency on the ivsc modules that prevents building the sensor drivers
# remove sensors from the dkms file
sed -i '/\[[4,5,6,7]\]/d' dkms.conf
sed -i '/\[[3,4,5,6,7]\]/d' dkms.conf
# disable sensor modules in the Makefile
sed -i 's/export CONFIG_VIDEO_OV/#export CONFIG_VIDEO_OV/g' Makefile
sed -i 's/export CONFIG_VIDEO_HM/#export CONFIG_VIDEO_HM/g' Makefile
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
# Copyright (c) 2021 Intel Corporation.

export CONFIG_VIDEO_INTEL_IPU6 = m
export CONFIG_IPU_ISYS_BRIDGE = y
obj-y += drivers/media/pci/intel/

export CONFIG_VIDEO_HM11B1 = m
export CONFIG_VIDEO_OV01A1S = m
export CONFIG_VIDEO_OV01A10 = m
export CONFIG_VIDEO_OV02C10 = m
export CONFIG_POWER_CTRL_LOGIC = m
export CONFIG_VIDEO_OV2740 = m
obj-y += drivers/media/i2c/

KERNELRELEASE ?= $(shell uname -r)
Expand Down
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Alder Lake platforms. There are 4 repositories that provide the complete setup:

## Content of this repository:
- IPU6 kernel driver
- Drivers for HM11B1, OV01A1S, OV01A10 and OV02C10 sensors
- Drivers for HM11B1, OV01A1S, OV01A10, OV02C10 and OV2740 sensors

## Build instructions:
Three ways are available:
Expand All @@ -23,7 +23,7 @@ Three ways are available:
- Tested with kernel 5.15
- Check out kernel
- Patch the diff files in `patch` folder
- Copy repo content to kernel source
- Copy repo content to kernel source (except Makefile and drivers/media/i2c/{Kconfig,Makefile}, will change manually)
- Modify related Kconfig and Makefile
- Add config in LinuxRoot/drivers/media/i2c/Kconfig *(for kernel 5.18+, use `VIDEO_DEV` instead of `VIDEO_V4L2` in `depends on` section)*
```conf
Expand All @@ -41,7 +41,6 @@ Three ways are available:

config VIDEO_OV01A1S
tristate "OmniVision OV01A1S sensor support"
depends on POWER_CTRL_LOGIC
depends on VIDEO_V4L2 && I2C
depends on ACPI || COMPILE_TEST
select MEDIA_CONTROLLER
Expand All @@ -56,7 +55,6 @@ Three ways are available:

config VIDEO_HM11B1
tristate "Himax HM11B1 sensor support"
depends on POWER_CTRL_LOGIC
depends on VIDEO_V4L2 && I2C
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
Expand Down
10 changes: 5 additions & 5 deletions dkms.conf
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ BUILT_MODULE_NAME[2]="intel-ipu6-psys"
BUILT_MODULE_LOCATION[2]="drivers/media/pci/intel/ipu6"
DEST_MODULE_LOCATION[2]="/kernel/drivers/media/pci/intel/ipu6"

BUILT_MODULE_NAME[3]="power_ctrl_logic"
BUILT_MODULE_NAME[3]="hm11b1"
BUILT_MODULE_LOCATION[3]="drivers/media/i2c"
DEST_MODULE_LOCATION[3]="/kernel/drivers/media/i2c"

BUILT_MODULE_NAME[4]="hm11b1"
BUILT_MODULE_NAME[4]="ov01a1s"
BUILT_MODULE_LOCATION[4]="drivers/media/i2c"
DEST_MODULE_LOCATION[4]="/kernel/drivers/media/i2c"

BUILT_MODULE_NAME[5]="ov01a1s"
BUILT_MODULE_NAME[5]="ov01a10"
BUILT_MODULE_LOCATION[5]="drivers/media/i2c"
DEST_MODULE_LOCATION[5]="/kernel/drivers/media/i2c"

BUILT_MODULE_NAME[6]="ov01a10"
BUILT_MODULE_NAME[6]="ov02c10"
BUILT_MODULE_LOCATION[6]="drivers/media/i2c"
DEST_MODULE_LOCATION[6]="/kernel/drivers/media/i2c"

BUILT_MODULE_NAME[7]="ov02c10"
BUILT_MODULE_NAME[7]="ov2740"
BUILT_MODULE_LOCATION[7]="drivers/media/i2c"
DEST_MODULE_LOCATION[7]="/kernel/drivers/media/i2c"

Expand Down
1 change: 1 addition & 0 deletions drivers/media/i2c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ obj-$(CONFIG_VIDEO_OV01A1S) += ov01a1s.o
obj-$(CONFIG_VIDEO_OV01A10) += ov01a10.o
obj-$(CONFIG_VIDEO_OV02C10) += ov02c10.o
obj-$(CONFIG_POWER_CTRL_LOGIC) += power_ctrl_logic.o
obj-$(CONFIG_VIDEO_OV2740) += ov2740.o
115 changes: 99 additions & 16 deletions drivers/media/i2c/hm11b1.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2020-2021 Intel Corporation.
// Copyright (c) 2020-2022 Intel Corporation.

#include <asm/unaligned.h>
#include <linux/acpi.h>
Expand All @@ -11,7 +11,12 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472)
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#elif IS_ENABLED(CONFIG_POWER_CTRL_LOGIC)
#include "power_ctrl_logic.h"
#endif

#define HM11B1_LINK_FREQ_384MHZ 384000000ULL
#define HM11B1_SCLK 72000000LL
Expand Down Expand Up @@ -455,6 +460,20 @@ struct hm11b1 {
/* To serialize asynchronus callbacks */
struct mutex mutex;

/* i2c client */
struct i2c_client *client;

#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472)
/* GPIO for reset */
struct gpio_desc *reset_gpio;
/* GPIO for powerdown */
struct gpio_desc *powerdown_gpio;
/* GPIO for clock enable */
struct gpio_desc *clken_gpio;
/* GPIO for privacy LED */
struct gpio_desc *pled_gpio;
#endif

/* Streaming on/off */
bool streaming;
};
Expand Down Expand Up @@ -482,9 +501,24 @@ static u64 to_pixels_per_line(u32 hts, u32 f_index)
return ppl;
}

static void hm11b1_set_power(struct hm11b1 *hm11b1, int on)
{
#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472)
if (!(hm11b1->reset_gpio && hm11b1->powerdown_gpio))
return;
gpiod_set_value_cansleep(hm11b1->reset_gpio, on);
gpiod_set_value_cansleep(hm11b1->powerdown_gpio, on);
gpiod_set_value_cansleep(hm11b1->clken_gpio, on);
gpiod_set_value_cansleep(hm11b1->pled_gpio, on);
msleep(20);
#elif IS_ENABLED(CONFIG_POWER_CTRL_LOGIC)
power_ctrl_logic_set_power(on);
#endif
}

static int hm11b1_read_reg(struct hm11b1 *hm11b1, u16 reg, u16 len, u32 *val)
{
struct i2c_client *client = v4l2_get_subdevdata(&hm11b1->sd);
struct i2c_client *client = hm11b1->client;
struct i2c_msg msgs[2];
u8 addr_buf[2];
u8 data_buf[4] = {0};
Expand Down Expand Up @@ -514,7 +548,7 @@ static int hm11b1_read_reg(struct hm11b1 *hm11b1, u16 reg, u16 len, u32 *val)

static int hm11b1_write_reg(struct hm11b1 *hm11b1, u16 reg, u16 len, u32 val)
{
struct i2c_client *client = v4l2_get_subdevdata(&hm11b1->sd);
struct i2c_client *client = hm11b1->client;
u8 buf[6];
int ret = 0;

Expand All @@ -534,7 +568,7 @@ static int hm11b1_write_reg(struct hm11b1 *hm11b1, u16 reg, u16 len, u32 val)
static int hm11b1_write_reg_list(struct hm11b1 *hm11b1,
const struct hm11b1_reg_list *r_list)
{
struct i2c_client *client = v4l2_get_subdevdata(&hm11b1->sd);
struct i2c_client *client = hm11b1->client;
unsigned int i;
int ret = 0;

Expand All @@ -554,7 +588,7 @@ static int hm11b1_write_reg_list(struct hm11b1 *hm11b1,

static int hm11b1_update_digital_gain(struct hm11b1 *hm11b1, u32 d_gain)
{
struct i2c_client *client = v4l2_get_subdevdata(&hm11b1->sd);
struct i2c_client *client = hm11b1->client;
int ret = 0;

ret = hm11b1_write_reg(hm11b1, HM11B1_REG_DGTL_GAIN, 2, d_gain);
Expand Down Expand Up @@ -585,7 +619,7 @@ static int hm11b1_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct hm11b1 *hm11b1 = container_of(ctrl->handler,
struct hm11b1, ctrl_handler);
struct i2c_client *client = v4l2_get_subdevdata(&hm11b1->sd);
struct i2c_client *client = hm11b1->client;
s64 exposure_max;
int ret = 0;

Expand Down Expand Up @@ -732,12 +766,12 @@ static void hm11b1_update_pad_format(const struct hm11b1_mode *mode,

static int hm11b1_start_streaming(struct hm11b1 *hm11b1)
{
struct i2c_client *client = v4l2_get_subdevdata(&hm11b1->sd);
struct i2c_client *client = hm11b1->client;
const struct hm11b1_reg_list *reg_list;
int link_freq_index;
int ret = 0;

power_ctrl_logic_set_power(1);
hm11b1_set_power(hm11b1, 1);
link_freq_index = hm11b1->cur_mode->link_freq_index;
reg_list = &link_freq_configs[link_freq_index].reg_list;
ret = hm11b1_write_reg_list(hm11b1, reg_list);
Expand Down Expand Up @@ -767,18 +801,18 @@ static int hm11b1_start_streaming(struct hm11b1 *hm11b1)

static void hm11b1_stop_streaming(struct hm11b1 *hm11b1)
{
struct i2c_client *client = v4l2_get_subdevdata(&hm11b1->sd);
struct i2c_client *client = hm11b1->client;

if (hm11b1_write_reg(hm11b1, HM11B1_REG_MODE_SELECT, 1,
HM11B1_MODE_STANDBY))
dev_err(&client->dev, "failed to stop streaming");
power_ctrl_logic_set_power(0);
hm11b1_set_power(hm11b1, 0);
}

static int hm11b1_set_stream(struct v4l2_subdev *sd, int enable)
{
struct hm11b1 *hm11b1 = to_hm11b1(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct i2c_client *client = hm11b1->client;
int ret = 0;

if (hm11b1->streaming == enable)
Expand Down Expand Up @@ -1002,7 +1036,7 @@ static const struct v4l2_subdev_internal_ops hm11b1_internal_ops = {

static int hm11b1_identify_module(struct hm11b1 *hm11b1)
{
struct i2c_client *client = v4l2_get_subdevdata(&hm11b1->sd);
struct i2c_client *client = hm11b1->client;
int ret;
u32 val;

Expand Down Expand Up @@ -1033,6 +1067,44 @@ static int hm11b1_remove(struct i2c_client *client)
return 0;
}

#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472)
static int hm11b1_parse_dt(struct hm11b1 *hm11b1)
{
struct device *dev = &hm11b1->client->dev;
int ret;

hm11b1->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
ret = PTR_ERR_OR_ZERO(hm11b1->reset_gpio);
if (ret < 0) {
dev_err(dev, "error while getting reset gpio: %d\n", ret);
return ret;
}

hm11b1->powerdown_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_HIGH);
ret = PTR_ERR_OR_ZERO(hm11b1->powerdown_gpio);
if (ret < 0) {
dev_err(dev, "error while getting powerdown gpio: %d\n", ret);
return ret;
}

hm11b1->clken_gpio = devm_gpiod_get(dev, "clken", GPIOD_OUT_HIGH);
ret = PTR_ERR_OR_ZERO(hm11b1->clken_gpio);
if (ret < 0) {
dev_err(dev, "error while getting clken_gpio gpio: %d\n", ret);
return ret;
}

hm11b1->pled_gpio = devm_gpiod_get(dev, "pled", GPIOD_OUT_HIGH);
ret = PTR_ERR_OR_ZERO(hm11b1->pled_gpio);
if (ret < 0) {
dev_err(dev, "error while getting pled gpio: %d\n", ret);
return ret;
}

return 0;
}
#endif

static int hm11b1_probe(struct i2c_client *client)
{
struct hm11b1 *hm11b1;
Expand All @@ -1041,14 +1113,23 @@ static int hm11b1_probe(struct i2c_client *client)
hm11b1 = devm_kzalloc(&client->dev, sizeof(*hm11b1), GFP_KERNEL);
if (!hm11b1)
return -ENOMEM;
hm11b1->client = client;

#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472)
ret = hm11b1_parse_dt(hm11b1);
if (ret < 0)
return -EPROBE_DEFER;
#elif IS_ENABLED(CONFIG_POWER_CTRL_LOGIC)
if (power_ctrl_logic_set_power(1))
return -EPROBE_DEFER;
#endif
hm11b1_set_power(hm11b1, 1);

v4l2_i2c_subdev_init(&hm11b1->sd, client, &hm11b1_subdev_ops);
power_ctrl_logic_set_power(0);
power_ctrl_logic_set_power(1);
ret = hm11b1_identify_module(hm11b1);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
return ret;
goto probe_error_power_off;
}

mutex_init(&hm11b1->mutex);
Expand Down Expand Up @@ -1089,7 +1170,7 @@ static int hm11b1_probe(struct i2c_client *client)
pm_runtime_enable(&client->dev);
pm_runtime_idle(&client->dev);

power_ctrl_logic_set_power(0);
hm11b1_set_power(hm11b1, 0);
return 0;

probe_error_media_entity_cleanup:
Expand All @@ -1099,6 +1180,8 @@ static int hm11b1_probe(struct i2c_client *client)
v4l2_ctrl_handler_free(hm11b1->sd.ctrl_handler);
mutex_destroy(&hm11b1->mutex);

probe_error_power_off:
hm11b1_set_power(hm11b1, 0);
return ret;
}

Expand Down

0 comments on commit f771bd3

Please sign in to comment.