* Re: [PATCH 3/9] media: i2c: hm1092: add Himax HM1092 mono NIR sensor driver
From: Bryan O'Donoghue @ 2026-06-10 12:11 UTC (permalink / raw)
To: Ramshouriesh, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Mauro Carvalho Chehab,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy
In-Reply-To: <20260610-a14-himax-hm1092-v1-3-0c9907da47ed@gmail.com>
On 10/06/2026 12:09, Ramshouriesh wrote:
> Add a v4l2 subdev driver for the Himax HM1092 monochrome near-IR sensor,
> used as the Windows-Hello IR camera on the ASUS Zenbook A14.
>
> The driver also drives the IR illuminator (a PM8550 flash LED referenced
> through the generic "leds" property): while streaming it strobes the
> illuminator at ~10 Hz, lighting the capture while keeping the average IR
> LED power down.
Drop references to PM8550 as its a qcomism and this is a i2c sensor.
>
> Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
And I think you can/should reference a series where this driver is used
but split the driver submission itself from the SoC/platform specific.
You want to target Sakari's tree - land the driver then enable the
platform code on top, so structure your patchworking around that strategy.
> ---
> drivers/media/i2c/Kconfig | 14 +
> drivers/media/i2c/Makefile | 1 +
> drivers/media/i2c/hm1092.c | 685 ++++++++++++++++++++++++++++++++++++++++
> drivers/media/i2c/hm1092_regs.h | 223 +++++++++++++
> 4 files changed, 923 insertions(+)
>
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index 5d173e0ecf42..8ee3ee15e9df 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -137,6 +137,20 @@ config VIDEO_HI847
> To compile this driver as a module, choose M here: the
> module will be called hi847.
>
> +config VIDEO_HM1092
> + tristate "Himax HM1092 sensor support"
> + select V4L2_CCI_I2C
> + help
> + This is a Video4Linux2 sensor driver for the Himax
> + HM1092 1MP mono IR camera used for face authentication
> + on Snapdragon X laptops (ASUS Zenbook A14 etc.).
> +
> + Register tables were reverse-engineered from the Qualcomm
> + Chromatix sensor module shipped in the Windows BSP.
Not specific to Qcom - sensor vendors target ISP vendors like Intel,
Qcom and others. You might easily say the same "this is used in IPU7"
for this sensor for all we know.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called hm1092.
> +
> config VIDEO_IMX111
> tristate "Sony IMX111 sensor support"
> select V4L2_CCI_I2C
> diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
> index e45359efe0e4..6507c173d0fa 100644
> --- a/drivers/media/i2c/Makefile
> +++ b/drivers/media/i2c/Makefile
> @@ -45,6 +45,7 @@ obj-$(CONFIG_VIDEO_GC2145) += gc2145.o
> obj-$(CONFIG_VIDEO_HI556) += hi556.o
> obj-$(CONFIG_VIDEO_HI846) += hi846.o
> obj-$(CONFIG_VIDEO_HI847) += hi847.o
> +obj-$(CONFIG_VIDEO_HM1092) += hm1092.o
> obj-$(CONFIG_VIDEO_I2C) += video-i2c.o
> obj-$(CONFIG_VIDEO_IMX111) += imx111.o
> obj-$(CONFIG_VIDEO_IMX208) += imx208.o
> diff --git a/drivers/media/i2c/hm1092.c b/drivers/media/i2c/hm1092.c
> new file mode 100644
> index 000000000000..90968ee29d81
> --- /dev/null
> +++ b/drivers/media/i2c/hm1092.c
> @@ -0,0 +1,685 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Himax HM1092 image sensor driver draft.
> + *
> + * Register tables were extracted from Qualcomm Chromatix sensor module
> + * com.qti.sensormodule.hm1092.bin. Keep hm1092_regs.h next to this file, or
> + * fold the generated tables into this source before upstream submission.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/i2c.h>
> +#include <linux/led-class-flash.h>
> +#include <linux/leds.h>
> +#include <linux/module.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/workqueue.h>
> +#include <media/v4l2-cci.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-fwnode.h>
> +
> +#include "hm1092_regs.h"
> +
> +#define HM1092_LINK_FREQ_400MHZ 400000000ULL
> +#define HM1092_MCLK 24000000
> +#define HM1092_BITS_PER_SAMPLE 10
> +
> +#define HM1092_REG_STREAM CCI_REG8(0x0100)
> +
> +#define HM1092_FLASH_TIMEOUT_US 50000 /* 0.05 s on per pulse */
> +#define HM1092_FLASH_REFIRE_MS 100 /* 0.1 s period -> 10 Hz blink */
> +
> +struct hm1092_mode {
> + u32 width;
> + u32 height;
> + u32 hts;
> + u32 vts;
> +};
> +
> +static const struct hm1092_mode hm1092_mode_560x360 = {
> + .width = 560,
> + .height = 360,
> + .hts = 0x0650,
> + .vts = 0x02ee,
> +};
> +
> +static const char * const hm1092_supply_names[] = {
> + "dovdd",
> + "avdd",
> + "dvdd",
> +};
> +
> +static const char * const hm1092_test_pattern_menu[] = {
> + "Disabled",
> + "Mode 1",
> + "Mode 2",
> + "Mode 3",
> + "Mode 4",
> +};
> +
> +static const s64 hm1092_link_freq_menu[] = {
> + HM1092_LINK_FREQ_400MHZ,
> +};
> +
> +struct hm1092 {
> + struct device *dev;
> + struct v4l2_subdev sd;
> + struct media_pad pad;
> + struct v4l2_ctrl_handler ctrl_handler;
> + struct regmap *regmap;
> + struct clk *img_clk;
> + struct gpio_desc *reset;
> + struct regulator_bulk_data supplies[ARRAY_SIZE(hm1092_supply_names)];
> + struct v4l2_ctrl *link_freq;
> + struct v4l2_ctrl *pixel_rate;
> + struct v4l2_ctrl *hblank;
> + struct v4l2_ctrl *vblank;
> + u8 mipi_lanes;
> +
> + /* Optional IR illuminator driven while streaming (see flash notes). */
> + struct led_classdev_flash *flash;
> + struct delayed_work flash_work;
> +};
> +
> +/*
> + * (Re)arm and fire the flash at full current. The qcom flash controller does an
> + * internal disable+enable on each strobe and the hardware safety-timeout turns
> + * the LED off on its own, so brightness/timeout must be programmed every time or
> + * the re-fire is a no-op. Re-firing well within the timeout keeps the LED lit
> + * continuously and near its (slightly declining) peak brightness.
> + */
> +static void hm1092_flash_fire(struct hm1092 *hm1092)
> +{
> + struct led_classdev_flash *flash = hm1092->flash;
> +
> + /*
> + * Release the controller's flash-current accounting first (a bare
> + * re-strobe is treated as "current still in use" and re-fires at 0 mA),
> + * then re-arm at full current and strobe.
> + */
> + led_set_flash_strobe(flash, false);
> + led_set_flash_brightness(flash, flash->brightness.max);
> + led_set_flash_timeout(flash, HM1092_FLASH_TIMEOUT_US);
> + led_set_flash_strobe(flash, true);
> +}
> +
> +static void hm1092_flash_enable(struct hm1092 *hm1092)
> +{
> + if (!hm1092->flash)
> + return;
> +
> + hm1092_flash_fire(hm1092);
> + schedule_delayed_work(&hm1092->flash_work,
> + msecs_to_jiffies(HM1092_FLASH_REFIRE_MS));
> +}
> +
> +static void hm1092_flash_disable(struct hm1092 *hm1092)
> +{
> + if (!hm1092->flash)
> + return;
> +
> + cancel_delayed_work_sync(&hm1092->flash_work);
> + led_set_flash_strobe(hm1092->flash, false);
> +}
> +
> +static void hm1092_flash_work(struct work_struct *work)
> +{
> + struct hm1092 *hm1092 =
> + container_of(to_delayed_work(work), struct hm1092, flash_work);
> +
> + hm1092_flash_fire(hm1092);
> + schedule_delayed_work(&hm1092->flash_work,
> + msecs_to_jiffies(HM1092_FLASH_REFIRE_MS));
> +}
> +
> +static inline struct hm1092 *to_hm1092(struct v4l2_subdev *sd)
> +{
> + return container_of(sd, struct hm1092, sd);
> +}
> +
> +static int hm1092_write_regs(struct hm1092 *hm1092,
> + const struct hm1092_reg *regs, unsigned int len)
> +{
> + int ret = 0;
> + unsigned int i;
reverse
xmas
tree for preference.
> +
> + for (i = 0; i < len; i++) {
> + cci_write(hm1092->regmap, CCI_REG8(regs[i].address),
> + regs[i].val, &ret);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int hm1092_set_test_pattern(struct hm1092 *hm1092, int pattern)
> +{
> + switch (pattern) {
> + case 0:
> + return hm1092_write_regs(hm1092, hm1092_test_pattern_mode0,
> + ARRAY_SIZE(hm1092_test_pattern_mode0));
> + case 1:
> + return hm1092_write_regs(hm1092, hm1092_test_pattern_mode1,
> + ARRAY_SIZE(hm1092_test_pattern_mode1));
> + case 2:
> + return hm1092_write_regs(hm1092, hm1092_test_pattern_mode2,
> + ARRAY_SIZE(hm1092_test_pattern_mode2));
> + case 3:
> + return hm1092_write_regs(hm1092, hm1092_test_pattern_mode3,
> + ARRAY_SIZE(hm1092_test_pattern_mode3));
> + case 4:
> + return hm1092_write_regs(hm1092, hm1092_test_pattern_mode4,
> + ARRAY_SIZE(hm1092_test_pattern_mode4));
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int hm1092_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> + struct hm1092 *hm1092 = container_of(ctrl->handler, struct hm1092,
> + ctrl_handler);
> + int ret = 0;
> +
> + if (!pm_runtime_get_if_in_use(hm1092->dev))
> + return 0;
This seems strange. Like you're returning zero for an error case.
> +
> + switch (ctrl->id) {
> + case V4L2_CID_TEST_PATTERN:
> + ret = hm1092_set_test_pattern(hm1092, ctrl->val);
> + break;
> + case V4L2_CID_ANALOGUE_GAIN:
> + case V4L2_CID_EXPOSURE:
> + /* TODO: write to the sensor's exposure/gain registers once
> + * we know which Chromatix middle*Addr fields point at them.
> + */
> + ret = 0;
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> +
> + pm_runtime_put(hm1092->dev);
> +
> + return ret;
> +}
> +
> +static const struct v4l2_ctrl_ops hm1092_ctrl_ops = {
> + .s_ctrl = hm1092_set_ctrl,
> +};
> +
> +static int hm1092_init_controls(struct hm1092 *hm1092)
> +{
> + struct v4l2_ctrl_handler *ctrl_hdlr = &hm1092->ctrl_handler;
> + const struct hm1092_mode *mode = &hm1092_mode_560x360;
> + struct v4l2_fwnode_device_properties props;
> + s64 hblank, pixel_rate;
> + int ret;
> +
> + v4l2_ctrl_handler_init(ctrl_hdlr, 6);
> +
> + hm1092->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
> + &hm1092_ctrl_ops,
> + V4L2_CID_LINK_FREQ,
> + 0, 0,
> + hm1092_link_freq_menu);
> + if (hm1092->link_freq)
> + hm1092->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> + pixel_rate = div_u64(HM1092_LINK_FREQ_400MHZ * 2 * hm1092->mipi_lanes,
> + HM1092_BITS_PER_SAMPLE);
> + hm1092->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &hm1092_ctrl_ops,
> + V4L2_CID_PIXEL_RATE, 0,
> + pixel_rate, 1, pixel_rate);
> +
> + hblank = mode->hts - mode->width;
> + hm1092->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &hm1092_ctrl_ops,
> + V4L2_CID_HBLANK, hblank, hblank, 1,
> + hblank);
> + if (hm1092->hblank)
> + hm1092->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> + hm1092->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &hm1092_ctrl_ops,
> + V4L2_CID_VBLANK,
> + mode->vts - mode->height,
> + 0xffff - mode->height, 1,
> + mode->vts - mode->height);
> + if (hm1092->vblank)
> + hm1092->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> + /* Mandatory controls for libcamera. Conservative defaults until we
> + * RE the exposure/gain register address layout from the Chromatix
> + * sensormodule (middleCoarseIntgTimeAddr / shortGlobalGainAddr).
> + */
> + v4l2_ctrl_new_std(ctrl_hdlr, &hm1092_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
> + 0x10, 0xff, 1, 0x10);
> + v4l2_ctrl_new_std(ctrl_hdlr, &hm1092_ctrl_ops, V4L2_CID_EXPOSURE,
> + 1, mode->vts - 4, 1, mode->vts - 4);
> +
> + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &hm1092_ctrl_ops,
> + V4L2_CID_TEST_PATTERN,
> + ARRAY_SIZE(hm1092_test_pattern_menu) - 1,
> + 0, 0, hm1092_test_pattern_menu);
> +
> + ret = v4l2_fwnode_device_parse(hm1092->dev, &props);
> + if (ret)
> + return ret;
> +
> + v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &hm1092_ctrl_ops, &props);
> +
> + if (ctrl_hdlr->error)
> + return ctrl_hdlr->error;
> +
> + hm1092->sd.ctrl_handler = ctrl_hdlr;
> +
> + return 0;
> +}
> +
> +static void hm1092_update_pad_format(struct v4l2_mbus_framefmt *fmt)
> +{
> + fmt->width = hm1092_mode_560x360.width;
> + fmt->height = hm1092_mode_560x360.height;
> + fmt->code = MEDIA_BUS_FMT_Y10_1X10;
> + fmt->field = V4L2_FIELD_NONE;
> +}
> +
> +static int hm1092_enable_streams(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state,
> + u32 pad, u64 streams_mask)
> +{
> + struct hm1092 *hm1092 = to_hm1092(sd);
> + int ret;
> +
> + ret = pm_runtime_resume_and_get(hm1092->dev);
> + if (ret)
> + return ret;
> +
> + ret = hm1092_write_regs(hm1092, hm1092_init_regs,
> + ARRAY_SIZE(hm1092_init_regs));
> + if (ret) {
> + dev_err(hm1092->dev, "failed to write init registers\n");
> + goto out;
> + }
> +
> + ret = __v4l2_ctrl_handler_setup(hm1092->sd.ctrl_handler);
> + if (ret)
> + goto out;
> +
> + ret = hm1092_write_regs(hm1092, hm1092_start_streaming,
> + ARRAY_SIZE(hm1092_start_streaming));
> + if (ret)
> + dev_err(hm1092->dev, "failed to start streaming\n");
> + else
> + hm1092_flash_enable(hm1092);
> +
> +out:
> + if (ret)
> + pm_runtime_put(hm1092->dev);
> +
> + return ret;
> +}
> +
> +static int hm1092_disable_streams(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state,
> + u32 pad, u64 streams_mask)
> +{
> + struct hm1092 *hm1092 = to_hm1092(sd);
> + int ret = 0;
> +
> + hm1092_flash_disable(hm1092);
> + cci_write(hm1092->regmap, HM1092_REG_STREAM, 0, &ret);
> + pm_runtime_put(hm1092->dev);
> +
> + return ret;
> +}
> +
> +static int hm1092_set_format(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state,
> + struct v4l2_subdev_format *fmt)
> +{
> + hm1092_update_pad_format(&fmt->format);
> + *v4l2_subdev_state_get_format(state, fmt->pad) = fmt->format;
> +
> + return 0;
> +}
> +
> +static int hm1092_enum_mbus_code(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state,
> + struct v4l2_subdev_mbus_code_enum *code)
> +{
> + if (code->index)
> + return -EINVAL;
> +
> + code->code = MEDIA_BUS_FMT_Y10_1X10;
> +
> + return 0;
> +}
> +
> +static int hm1092_enum_frame_size(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state,
> + struct v4l2_subdev_frame_size_enum *fse)
> +{
> + if (fse->index)
> + return -EINVAL;
> +
> + if (fse->code != MEDIA_BUS_FMT_Y10_1X10)
> + return -EINVAL;
> +
> + fse->min_width = hm1092_mode_560x360.width;
> + fse->max_width = hm1092_mode_560x360.width;
> + fse->min_height = hm1092_mode_560x360.height;
> + fse->max_height = hm1092_mode_560x360.height;
> +
> + return 0;
> +}
> +
> +static int hm1092_init_state(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state)
> +{
> + hm1092_update_pad_format(v4l2_subdev_state_get_format(state, 0));
> +
> + return 0;
> +}
> +
> +static const struct v4l2_subdev_video_ops hm1092_video_ops = {
> + .s_stream = v4l2_subdev_s_stream_helper,
> +};
> +
> +static const struct v4l2_subdev_pad_ops hm1092_pad_ops = {
> + .set_fmt = hm1092_set_format,
> + .get_fmt = v4l2_subdev_get_fmt,
> + .enum_mbus_code = hm1092_enum_mbus_code,
> + .enum_frame_size = hm1092_enum_frame_size,
> + .enable_streams = hm1092_enable_streams,
> + .disable_streams = hm1092_disable_streams,
> +};
> +
> +static const struct v4l2_subdev_ops hm1092_subdev_ops = {
> + .video = &hm1092_video_ops,
> + .pad = &hm1092_pad_ops,
> +};
> +
> +static const struct media_entity_operations hm1092_entity_ops = {
> + .link_validate = v4l2_subdev_link_validate,
> +};
> +
> +static const struct v4l2_subdev_internal_ops hm1092_internal_ops = {
> + .init_state = hm1092_init_state,
> +};
> +
> +static int hm1092_check_hwcfg(struct hm1092 *hm1092)
> +{
> + struct v4l2_fwnode_endpoint bus_cfg = {
> + .bus_type = V4L2_MBUS_CSI2_DPHY,
> + };
> + struct device *dev = hm1092->dev;
> + struct fwnode_handle *ep, *fwnode = dev_fwnode(dev);
> + unsigned long link_freq_bitmap;
> + int ret;
> +
> + ep = fwnode_graph_get_endpoint_by_id(fwnode, 0, 0, 0);
> + if (!ep)
> + return dev_err_probe(dev, -EPROBE_DEFER,
> + "waiting for fwnode graph endpoint\n");
> +
> + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
> + fwnode_handle_put(ep);
> + if (ret)
> + return dev_err_probe(dev, ret, "parsing endpoint failed\n");
> +
> + ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies,
> + bus_cfg.nr_of_link_frequencies,
> + hm1092_link_freq_menu,
> + ARRAY_SIZE(hm1092_link_freq_menu),
> + &link_freq_bitmap);
> + if (ret)
> + goto out;
> +
> + if (bus_cfg.bus.mipi_csi2.num_data_lanes != 1 &&
> + bus_cfg.bus.mipi_csi2.num_data_lanes != 2) {
> + ret = dev_err_probe(dev, -EINVAL,
> + "unsupported CSI2 data lanes: %u\n",
> + bus_cfg.bus.mipi_csi2.num_data_lanes);
> + goto out;
> + }
You have a hard-coded init sequence - does it really support both one
and two lane mode ?
Seems unlikely.
> +
> + hm1092->mipi_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
> +
> +out:
> + v4l2_fwnode_endpoint_free(&bus_cfg);
> + return ret;
> +}
> +
> +static int hm1092_get_pm_resources(struct hm1092 *hm1092)
> +{
> + unsigned int i;
> +
> + hm1092->reset = devm_gpiod_get_optional(hm1092->dev, "reset",
> + GPIOD_OUT_HIGH);
> + if (IS_ERR(hm1092->reset))
> + return dev_err_probe(hm1092->dev, PTR_ERR(hm1092->reset),
> + "failed to get reset gpio\n");
> +
> + for (i = 0; i < ARRAY_SIZE(hm1092_supply_names); i++)
> + hm1092->supplies[i].supply = hm1092_supply_names[i];
> +
> + return devm_regulator_bulk_get(hm1092->dev,
> + ARRAY_SIZE(hm1092_supply_names),
> + hm1092->supplies);
> +}
> +
> +static int hm1092_power_off(struct device *dev)
> +{
> + struct v4l2_subdev *sd = dev_get_drvdata(dev);
> + struct hm1092 *hm1092 = to_hm1092(sd);
> +
> + gpiod_set_value_cansleep(hm1092->reset, 1);
> + regulator_bulk_disable(ARRAY_SIZE(hm1092_supply_names),
> + hm1092->supplies);
> + clk_disable_unprepare(hm1092->img_clk);
> +
> + return 0;
> +}
> +
> +static int hm1092_power_on(struct device *dev)
> +{
> + struct v4l2_subdev *sd = dev_get_drvdata(dev);
> + struct hm1092 *hm1092 = to_hm1092(sd);
> + int ret;
> +
> + /*
> + * Sequence reverse-engineered from the Chromatix AeoB powerSetting:
> + * 1. enable all rails (~1 ms ramp per supply)
> + * 2. hold reset asserted
> + * 3. start MCLK and let the sensor clock for ~1 ms
> + * 4. release reset and wait 18 ms for the sensor to come up
> + */
> + ret = regulator_bulk_enable(ARRAY_SIZE(hm1092_supply_names),
> + hm1092->supplies);
> + if (ret)
> + return ret;
\n> + usleep_range(3000, 3500);
Your comment says 1 ms so it needs an update.
> +
> + if (hm1092->reset)
> + gpiod_set_value_cansleep(hm1092->reset, 1);
> +
> + ret = clk_prepare_enable(hm1092->img_clk);
> + if (ret) {
> + regulator_bulk_disable(ARRAY_SIZE(hm1092_supply_names),
> + hm1092->supplies);
> + return ret;
> + }
> + usleep_range(1000, 1200);
> +
> + if (hm1092->reset)
> + gpiod_set_value_cansleep(hm1092->reset, 0);
> + usleep_range(18000, 19000);
> +
> + return 0;
> +}
> +
> +static void hm1092_remove(struct i2c_client *client)
> +{
> + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> + struct hm1092 *hm1092 = to_hm1092(sd);
> +
> + v4l2_async_unregister_subdev(sd);
> + v4l2_subdev_cleanup(sd);
> + media_entity_cleanup(&sd->entity);
> + v4l2_ctrl_handler_free(sd->ctrl_handler);
> + pm_runtime_disable(hm1092->dev);
> + if (!pm_runtime_status_suspended(hm1092->dev)) {
> + hm1092_power_off(hm1092->dev);
> + pm_runtime_set_suspended(hm1092->dev);
> + }
> +}
> +
> +/* Optional: grab the IR illuminator flash LED referenced by the "leds" phandle. */
> +static int hm1092_get_flash(struct hm1092 *hm1092)
> +{
> + struct led_classdev *cdev;
> +
> + cdev = devm_of_led_get_optional(hm1092->dev, 0);
> + if (IS_ERR(cdev))
> + return dev_err_probe(hm1092->dev, PTR_ERR(cdev),
> + "failed to get IR illuminator LED\n");
> + if (!cdev)
> + return 0; /* no illuminator wired; capture still works */
Does checkpatch accept a comment on a line like that ?
> +
> + if (!(cdev->flags & LED_DEV_CAP_FLASH)) {
> + dev_warn(hm1092->dev,
> + "'leds' phandle is not a flash LED; IR illuminator disabled\n");
> + return 0;
> + }
> +
> + hm1092->flash = lcdev_to_flcdev(cdev);
> + INIT_DELAYED_WORK(&hm1092->flash_work, hm1092_flash_work);
> + dev_dbg(hm1092->dev, "IR illuminator flash linked (max %u uA)\n",
> + hm1092->flash->brightness.max);
\n> + return 0;
> +}
> +
> +static int hm1092_probe(struct i2c_client *client)
> +{
> + struct hm1092 *hm1092;
> + unsigned long freq;
> + int ret;
> +
> + hm1092 = devm_kzalloc(&client->dev, sizeof(*hm1092), GFP_KERNEL);
> + if (!hm1092)
> + return -ENOMEM;
> +
> + hm1092->dev = &client->dev;
> +
> + ret = hm1092_get_flash(hm1092);
> + if (ret)
> + return ret;
> +
> + hm1092->img_clk = devm_v4l2_sensor_clk_get(hm1092->dev, NULL);
> + if (IS_ERR(hm1092->img_clk))
> + return dev_err_probe(hm1092->dev, PTR_ERR(hm1092->img_clk),
> + "failed to get imaging clock\n");
> +
> + freq = clk_get_rate(hm1092->img_clk);
> + if (freq != HM1092_MCLK)
> + return dev_err_probe(hm1092->dev, -EINVAL,
> + "external clock %lu is not supported\n",
> + freq);
if (freq != ) {
// stuff goes here
}
> +
> + v4l2_i2c_subdev_init(&hm1092->sd, client, &hm1092_subdev_ops);
> +
> + ret = hm1092_check_hwcfg(hm1092);
> + if (ret)
> + return ret;
> +
> + ret = hm1092_get_pm_resources(hm1092);
> + if (ret)
> + return ret;
> +
> + hm1092->regmap = devm_cci_regmap_init_i2c(client, 16);
> + if (IS_ERR(hm1092->regmap))
> + return PTR_ERR(hm1092->regmap);
> +
> + ret = hm1092_power_on(hm1092->dev);
> + if (ret)
> + return dev_err_probe(hm1092->dev, ret, "failed to power on\n");
> +
> + ret = hm1092_init_controls(hm1092);
> + if (ret)
> + goto err_power_off;
> +
> + hm1092->sd.internal_ops = &hm1092_internal_ops;
> + hm1092->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> + hm1092->sd.entity.ops = &hm1092_entity_ops;
> + hm1092->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
> + hm1092->pad.flags = MEDIA_PAD_FL_SOURCE;
> + ret = media_entity_pads_init(&hm1092->sd.entity, 1, &hm1092->pad);
> + if (ret)
> + goto err_ctrls;
> +
> + hm1092->sd.state_lock = hm1092->ctrl_handler.lock;
> + ret = v4l2_subdev_init_finalize(&hm1092->sd);
> + if (ret)
> + goto err_entity;
> +
> + pm_runtime_set_active(hm1092->dev);
> + pm_runtime_enable(hm1092->dev);
> +
> + /*
> + * The HM1092 has no async sub-devices: no privacy LED, no lens, and
> + * its IR illuminator is a directly-driven led-class-flash (see
> + * hm1092_get_flash()), not a v4l2-flash subdev. Register the plain
> + * subdev rather than v4l2_async_register_subdev_sensor(), whose
> + * automatic privacy-LED lookup would otherwise reject the "leds"
> + * phandle that points at the illuminator.
> + */
> + ret = v4l2_async_register_subdev(&hm1092->sd);
> + if (ret)
> + goto err_subdev;
> +
> + pm_runtime_idle(hm1092->dev);
> + return 0;
> +
> +err_subdev:
> + pm_runtime_disable(hm1092->dev);
> + pm_runtime_set_suspended(hm1092->dev);
> + v4l2_subdev_cleanup(&hm1092->sd);
> +err_entity:
> + media_entity_cleanup(&hm1092->sd.entity);
> +err_ctrls:
> + v4l2_ctrl_handler_free(hm1092->sd.ctrl_handler);
> +err_power_off:
> + hm1092_power_off(hm1092->dev);
> +
> + return ret;
> +}
> +
> +static DEFINE_RUNTIME_DEV_PM_OPS(hm1092_pm_ops, hm1092_power_off,
> + hm1092_power_on, NULL);
> +
> +static const struct of_device_id hm1092_of_match[] = {
> + { .compatible = "himax,hm1092" },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, hm1092_of_match);
> +
> +static struct i2c_driver hm1092_i2c_driver = {
> + .driver = {
> + .name = "hm1092",
> + .pm = pm_sleep_ptr(&hm1092_pm_ops),
> + .of_match_table = hm1092_of_match,
> + },
> + .probe = hm1092_probe,
> + .remove = hm1092_remove,
> +};
> +
> +module_i2c_driver(hm1092_i2c_driver);
> +
> +MODULE_DESCRIPTION("Himax HM1092 sensor driver draft");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/media/i2c/hm1092_regs.h b/drivers/media/i2c/hm1092_regs.h
> new file mode 100644
> index 000000000000..4df2d5b49d81
> --- /dev/null
> +++ b/drivers/media/i2c/hm1092_regs.h
> @@ -0,0 +1,223 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* HM1092 register tables extracted from Qualcomm Chromatix sensor module.
> + * Source: com.qti.sensormodule.hm1092.bin
> + * Generator: hm1092-re/gen_hm1092_regs.py
This is great data.
> + * DO NOT HAND EDIT — regenerate from the bin.
This is not to be included in upstream though.
> + */
> +
> +struct hm1092_reg {
> + u16 address;
> + u8 val;
> +};
> +
> +static const struct hm1092_reg hm1092_init_regs[] = {
> + { 0x0103, 0x00 },
> + { 0x030a, 0x05 },
> + { 0x030d, 0x0c },
> + { 0x030f, 0x5a },
> + { 0x0307, 0x00 },
> + { 0x0309, 0x01 },
> + { 0x0387, 0x01 },
> + { 0x0100, 0x02 },
> + { 0x4265, 0x02 },
> + { 0x4002, 0x2b },
> + { 0x4001, 0x00 },
> + { 0x0101, 0x03 },
> + { 0x4024, 0x40 },
> + { 0x0203, 0xbe },
> + { 0x0202, 0x00 },
> + { 0x0341, 0xee },
> + { 0x0340, 0x02 },
> + { 0x0343, 0x50 },
> + { 0x0342, 0x06 },
> + { 0x0345, 0x30 },
> + { 0x0344, 0x00 },
> + { 0x0349, 0xad },
> + { 0x0348, 0x04 },
> + { 0x0347, 0x08 },
> + { 0x0346, 0x00 },
> + { 0x034b, 0xd5 },
> + { 0x034a, 0x02 },
> + { 0x5015, 0xb3 },
> + { 0x0350, 0x53 },
> + { 0x0361, 0x30 },
> + { 0x0360, 0x00 },
> + { 0x034d, 0x30 },
> + { 0x034c, 0x02 },
> + { 0x034f, 0x68 },
> + { 0x034e, 0x01 },
> + { 0x0390, 0x03 },
> + { 0x0383, 0x00 },
> + { 0x0387, 0x10 },
> + { 0x50dd, 0x01 },
> + { 0x50cb, 0x21 },
> + { 0x5005, 0x28 },
> + { 0x5004, 0x40 },
> + { 0x5007, 0x28 },
> + { 0x5006, 0x40 },
> + { 0x5011, 0x00 },
> + { 0x501d, 0x4c },
> + { 0x5013, 0x03 },
> + { 0x4131, 0x01 },
> + { 0x5283, 0x03 },
> + { 0x5282, 0xff },
> + { 0x5010, 0x20 },
> + { 0x4132, 0x20 },
> + { 0x50d5, 0xe0 },
> + { 0x50d7, 0x12 },
> + { 0x50bb, 0x14 },
> + { 0x50b7, 0x00 },
> + { 0x50b9, 0xff },
> + { 0x50b8, 0x70 },
> + { 0x50ba, 0xff },
> + { 0x50fa, 0x02 },
> + { 0x50b4, 0x00 },
> + { 0x50a2, 0x0b },
> + { 0x50ad, 0x07 },
> + { 0x50ac, 0x24 },
> + { 0x50af, 0x40 },
> + { 0x50ae, 0x20 },
> + { 0x50ab, 0x07 },
> + { 0x50aa, 0x22 },
> + { 0x50a7, 0x00 },
> + { 0x50a6, 0x00 },
> + { 0x5099, 0x11 },
> + { 0x509b, 0x03 },
> + { 0x50b3, 0x04 },
> + { 0x50a0, 0x30 },
> + { 0x5098, 0x00 },
> + { 0x52f2, 0x53 },
> + { 0x5209, 0x0c },
> + { 0x5216, 0x02 },
> + { 0x521e, 0x01 },
> + { 0x50e8, 0x00 },
> + { 0x5200, 0x60 },
> + { 0x5202, 0x00 },
> + { 0x5201, 0x80 },
> + { 0x5203, 0x01 },
> + { 0x5208, 0x0b },
> + { 0x520d, 0x40 },
> + { 0x520c, 0x15 },
> + { 0x5215, 0x04 },
> + { 0x50ea, 0x74 },
> + { 0x5214, 0x28 },
> + { 0x5218, 0x07 },
> + { 0x5217, 0x01 },
> + { 0x0310, 0x00 },
> + { 0x4b31, 0x06 },
> + { 0x4b3b, 0x02 },
> + { 0x4b45, 0x01 },
> + { 0x4b44, 0x0c },
> + { 0x4b47, 0x00 },
> + { 0x5101, 0x13 },
> + { 0x5100, 0x03 },
> + { 0x5103, 0x33 },
> + { 0x5102, 0x23 },
> + { 0x5105, 0x42 },
> + { 0x5104, 0x43 },
> + { 0x5106, 0x40 },
> + { 0x5119, 0x00 },
> + { 0x5118, 0x00 },
> + { 0x511b, 0x00 },
> + { 0x511a, 0x00 },
> + { 0x511d, 0x00 },
> + { 0x511c, 0x00 },
> + { 0x511e, 0x00 },
> + { 0x5131, 0x23 },
> + { 0x5130, 0x13 },
> + { 0x5133, 0x43 },
> + { 0x5132, 0x33 },
> + { 0x5135, 0x40 },
> + { 0x5134, 0x42 },
> + { 0x5136, 0x40 },
> + { 0x5149, 0x01 },
> + { 0x5148, 0x01 },
> + { 0x514b, 0x01 },
> + { 0x514a, 0x01 },
> + { 0x514d, 0x01 },
> + { 0x514c, 0x01 },
> + { 0x514e, 0x01 },
> + { 0x51c0, 0x00 },
> + { 0x51c6, 0x00 },
> + { 0x51cc, 0x00 },
> + { 0x51d2, 0x00 },
> + { 0x51d8, 0x00 },
> + { 0x51c1, 0x81 },
> + { 0x51c7, 0x81 },
> + { 0x51cd, 0x81 },
> + { 0x51d3, 0x81 },
> + { 0x51d9, 0x81 },
> + { 0x51c2, 0xec },
> + { 0x51c8, 0xec },
> + { 0x51ce, 0xec },
> + { 0x51d4, 0xec },
> + { 0x51da, 0xec },
> + { 0x51c3, 0x00 },
> + { 0x51c9, 0x00 },
> + { 0x51cf, 0x00 },
> + { 0x51d5, 0x00 },
> + { 0x51db, 0x00 },
> + { 0x51c4, 0x55 },
> + { 0x51ca, 0x55 },
> + { 0x51d0, 0x54 },
> + { 0x51d6, 0x53 },
> + { 0x51dc, 0x53 },
> + { 0x51c5, 0x44 },
> + { 0x51cb, 0x24 },
> + { 0x51d1, 0x24 },
> + { 0x51d7, 0x14 },
> + { 0x51dd, 0x14 },
> + { 0x51e0, 0x09 },
> + { 0x51e2, 0x04 },
> + { 0x51e4, 0x08 },
> + { 0x51e6, 0x08 },
> + { 0x51e1, 0x03 },
> + { 0x51e3, 0x03 },
> + { 0x51e5, 0x07 },
> + { 0x51e8, 0x04 },
> + { 0x51e7, 0x07 },
> + { 0x51e9, 0x46 },
> + { 0x51eb, 0x62 },
> + { 0x51ea, 0x43 },
> + { 0x51ed, 0x00 },
> + { 0x51ec, 0x61 },
> + { 0x51ee, 0x00 },
> + { 0x5206, 0x80 },
> + { 0x3110, 0x02 },
> + { 0x3704, 0x02 },
> + { 0x3704, 0x02 },
> + { 0x4b20, 0x9e },
> + { 0x4b18, 0x00 },
> + { 0x4b3e, 0x00 },
> + { 0x4b0e, 0x0e },
> + { 0x4800, 0xac },
> + { 0x0104, 0x01 },
> + { 0x0104, 0x00 },
> + { 0x4801, 0xae },
> + { 0x0000, 0x00 },
> + { 0x0037, 0x30 },
> +};
> +
> +static const struct hm1092_reg hm1092_start_streaming[] = {
> + { 0x0100, 0x01 },
> +};
> +
> +static const struct hm1092_reg hm1092_test_pattern_mode0[] = {
> + { 0x0601, 0x00 },
> +};
> +
> +static const struct hm1092_reg hm1092_test_pattern_mode1[] = {
> + { 0x0601, 0x01 },
> +};
> +
> +static const struct hm1092_reg hm1092_test_pattern_mode2[] = {
> + { 0x0601, 0x02 },
> +};
> +
> +static const struct hm1092_reg hm1092_test_pattern_mode3[] = {
> + { 0x0601, 0x03 },
> +};
> +
> +static const struct hm1092_reg hm1092_test_pattern_mode4[] = {
> + { 0x0601, 0x04 },
> +};
>
> --
> 2.53.0
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH 4/4] arm64: dts: qcom: sm6125: Fix QUSB2 compatible
From: Konrad Dybcio @ 2026-06-10 12:04 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Wesley Cheng, Iskren Chernev, Greg Kroah-Hartman,
Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Konrad Dybcio
In-Reply-To: <20260610-topic-8996_61x5_qusb2phy-v1-0-d7135980e78f@oss.qualcomm.com>
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
There are a couple issues with the current description:
1) The msm8996 compatible is wholly reused, without a SM6125-specific
primary compatible
2) MSM8996 has a different power setup (VDD powered through a RPMPD
power-domain vs a regulator)
3) MSM8996 uses a different init sequence
As part of fixing all of them, use a SM6125-specific compatible with a
SM6115 fallback.
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/sm6125.dtsi | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi
index 6e84c226948c..688548cef0f1 100644
--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi
@@ -681,7 +681,8 @@ gcc: clock-controller@1400000 {
};
hsusb_phy1: phy@1613000 {
- compatible = "qcom,msm8996-qusb2-phy";
+ compatible = "qcom,sm6125-qusb2-phy",
+ "qcom,sm6115-qusb2-phy";
reg = <0x01613000 0x180>;
#phy-cells = <0>;
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 3/4] arm64: dts: qcom: msm8996: Add VDD_MX to QUSB2 PHYs
From: Konrad Dybcio @ 2026-06-10 12:04 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Wesley Cheng, Iskren Chernev, Greg Kroah-Hartman,
Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Konrad Dybcio
In-Reply-To: <20260610-topic-8996_61x5_qusb2phy-v1-0-d7135980e78f@oss.qualcomm.com>
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
The QUSB2 PHYs are powered by (among others) the VDD_MX power rail.
Describe that in the DT.
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/msm8996.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 2f67e665996f..b7cd1928335c 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -3192,7 +3192,12 @@ hsusb_phy1: phy@7411000 {
clock-names = "cfg_ahb", "ref";
resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+
+ power-domains = <&rpmpd MSM8996_VDDMX>;
+ required-opps = <&rpmpd_opp4>;
+
nvmem-cells = <&qusb2p_hstx_trim>;
+
status = "disabled";
};
@@ -3206,7 +3211,12 @@ hsusb_phy2: phy@7412000 {
clock-names = "cfg_ahb", "ref";
resets = <&gcc GCC_QUSB2PHY_SEC_BCR>;
+
+ power-domains = <&rpmpd MSM8996_VDDMX>;
+ required-opps = <&rpmpd_opp4>;
+
nvmem-cells = <&qusb2s_hstx_trim>;
+
status = "disabled";
};
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 2/4] phy: qcom-qusb2: Fix SM6115 init sequence
From: Konrad Dybcio @ 2026-06-10 12:04 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Wesley Cheng, Iskren Chernev, Greg Kroah-Hartman,
Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Konrad Dybcio
In-Reply-To: <20260610-topic-8996_61x5_qusb2phy-v1-0-d7135980e78f@oss.qualcomm.com>
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
I don't know where the existing one came from, but it's apparently
wrong, according to both docs and a downstream DT [1]. Fix it up.
The updated values also happen to match SM6125, which will allow us
to fix that platform too.
[1] https://android.googlesource.com/kernel/msm-extra/devicetree/+/refs/heads/android-msm-bramble-4.19-android11-qpr1/qcom/bengal-usb.dtsi#145
Fixes: 7756f1d6369e ("phy: qcom-qusb2: Add configuration for SM4250 and SM6115")
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index eb93015be841..c304ccd9f31f 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -233,9 +233,9 @@ static const struct qusb2_phy_init_tbl msm8998_init_tbl[] = {
static const struct qusb2_phy_init_tbl sm6115_init_tbl[] = {
QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xf8),
- QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0x53),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0xb3),
QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0x81),
- QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0x17),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0xc0),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79),
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 1/4] dt-bindings: phy: qcom,qusb2: Straighten out SM6125 and MSM8996
From: Konrad Dybcio @ 2026-06-10 12:04 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Wesley Cheng, Iskren Chernev, Greg Kroah-Hartman,
Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Konrad Dybcio
In-Reply-To: <20260610-topic-8996_61x5_qusb2phy-v1-0-d7135980e78f@oss.qualcomm.com>
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
SM6125 DT currently uses just the MSM8996 compatible (without a primary
SM6125-specific one). This is not only wrong for the reasons of
violating guidelines, but also happens to not be valid.
The MSM8996 PHY is quite similar, although it requies a different init
sequence (for arch reasons). MSM8996 also needs different power
plumbing, as the VDD supply is fed through VDD_MX (which we define as
a power domain rather than a regulator), unlike on SM6125.
The init sequence seems to have been "good enough", but now that the
bindings clearly diverge, add a new compatible for SM6125 with a SM6115
fallback (as they seem to be an exact match from the SW interface POV).
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
.../devicetree/bindings/phy/qcom,qusb2-phy.yaml | 31 ++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
index 39851ba9de43..807d64aee547 100644
--- a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
@@ -30,6 +30,9 @@ properties:
- qcom,sdm660-qusb2-phy
- qcom,sm4250-qusb2-phy
- qcom,sm6115-qusb2-phy
+ - items:
+ - const: qcom,sm6125-qusb2-phy
+ - const: qcom,sm6115-qusb2-phy
- items:
- enum:
- qcom,sc7180-qusb2-phy
@@ -57,6 +60,12 @@ properties:
- const: ref
- const: iface
+ power-domains:
+ maxItems: 1
+
+ required-opps:
+ maxItems: 1
+
vdd-supply:
description:
Phandle to 0.9V regulator supply to PHY digital circuit.
@@ -160,7 +169,6 @@ required:
- "#phy-cells"
- clocks
- clock-names
- - vdd-supply
- vdda-pll-supply
- vdda-phy-dpdm-supply
- resets
@@ -182,6 +190,22 @@ allOf:
qcom,preemphasis-width: false
qcom,hsdisc-trim-value: false
+ # On MSM8996, VDD is supplied via the MX power domain
+ - if:
+ properties:
+ compatible:
+ const: qcom,msm8996-qusb2-phy
+ then:
+ required:
+ - power-domains
+ - required-opps
+ else:
+ properties:
+ power-domains: false
+ required-opps: false
+ required:
+ - vdd-supply
+
additionalProperties: false
examples:
@@ -196,10 +220,13 @@ examples:
<&gcc GCC_RX1_USB2_CLKREF_CLK>;
clock-names = "cfg_ahb", "ref";
- vdd-supply = <&pm8994_l28>;
vdda-pll-supply = <&pm8994_l12>;
vdda-phy-dpdm-supply = <&pm8994_l24>;
resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+
+ power-domains = <&rpmpd_mx>;
+ required-opps = <&rpmpd_opp4>;
+
nvmem-cells = <&qusb2p_hstx_trim>;
};
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 0/4] Fix up QUSB2 PHY description for MSM8996/SM61[12]5
From: Konrad Dybcio @ 2026-06-10 12:04 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Wesley Cheng, Iskren Chernev, Greg Kroah-Hartman,
Bjorn Andersson, Konrad Dybcio
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, Konrad Dybcio
The MSM8996 QUSB2PHY was not being guaranteed a power source.
The SM6125's QUSB2PHY was believed to be idential as the 96 one. It
wasn't. This series tackles that, freeing us of some dt checker
errors about vdd-supply not found on MSM8996 boards.
Compile-tested only, but docs confirm my findings..
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
Konrad Dybcio (4):
dt-bindings: phy: qcom,qusb2: Straighten out SM6125 and MSM8996
phy: qcom-qusb2: Fix SM6115 init sequence
arm64: dts: qcom: msm8996: Add VDD_MX to QUSB2 PHYs
arm64: dts: qcom: sm6125: Fix QUSB2 compatible
.../devicetree/bindings/phy/qcom,qusb2-phy.yaml | 31 ++++++++++++++++++++--
arch/arm64/boot/dts/qcom/msm8996.dtsi | 10 +++++++
arch/arm64/boot/dts/qcom/sm6125.dtsi | 3 ++-
drivers/phy/qualcomm/phy-qcom-qusb2.c | 4 +--
4 files changed, 43 insertions(+), 5 deletions(-)
---
base-commit: 49e02880ec0a8c378e811bc9d85da188d7c6204c
change-id: 20260610-topic-8996_61x5_qusb2phy-ad052b99e9de
Best regards,
--
Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH v3 2/2] phy: qcom-qmp-pcie: Add support for ipq5210 PCIe phys
From: Varadarajan Narayanan @ 2026-06-10 11:16 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel,
Varadarajan Narayanan
In-Reply-To: <20260610-pcie-phy-v3-0-334011b378d6@oss.qualcomm.com>
Add support for a PCIe phys found on Qualcomm ipq5210 platform.
Signed-off-by: Varadarajan Narayanan <varadarajan.narayanan@oss.qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 129 +++++++++++++++++++++++++++++++
1 file changed, 129 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
index 75afbd15aaf4..2bf00e0e125a 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
@@ -514,6 +514,89 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
};
+static const struct qmp_phy_init_tbl ipq5210_gen3x1_pcie_ep_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TIMER, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x23),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x23),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x19),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xfe),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE0, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xfe),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x10),
+};
+
+static const struct qmp_phy_init_tbl ipq5210_gen3x1_pcie_ep_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x61),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1e),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xf0),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x2f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xd3),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04),
+};
+
+static const struct qmp_phy_init_tbl ipq5210_gen3x1_pcie_ep_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG1, 0x11),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG1, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG4, 0xff),
+};
+
static const struct qmp_phy_init_tbl ipq9574_gen3x1_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01),
@@ -3613,6 +3696,49 @@ static const struct qmp_phy_cfg ipq6018_pciephy_cfg = {
.phy_status = PHYSTATUS,
};
+static const struct qmp_phy_cfg ipq5210_gen3x1_pciephy_cfg = {
+ .lanes = 1,
+
+ .offsets = &qmp_pcie_offsets_v4x1,
+
+ .tbls = {
+ .serdes = ipq9574_gen3x1_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_serdes_tbl),
+ .tx = ipq8074_pcie_gen3_tx_tbl,
+ .tx_num = ARRAY_SIZE(ipq8074_pcie_gen3_tx_tbl),
+ .rx = ipq9574_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(ipq9574_pcie_rx_tbl),
+ .pcs = ipq9574_gen3x1_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_pcs_tbl),
+ .pcs_misc = ipq9574_gen3x1_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_pcs_misc_tbl),
+ },
+
+ .tbls_ep = &(const struct qmp_phy_cfg_tbls) {
+ .serdes = ipq5210_gen3x1_pcie_ep_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(ipq5210_gen3x1_pcie_ep_serdes_tbl),
+ .tx = ipq6018_pcie_tx_tbl,
+ .tx_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl),
+ .rx = ipq5210_gen3x1_pcie_ep_rx_tbl,
+ .rx_num = ARRAY_SIZE(ipq5210_gen3x1_pcie_ep_rx_tbl),
+ .pcs = ipq6018_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl),
+ .pcs_misc = ipq5210_gen3x1_pcie_ep_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(ipq5210_gen3x1_pcie_ep_pcs_misc_tbl),
+ },
+
+ .reset_list = ipq8074_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
+ .vreg_list = NULL,
+ .num_vregs = 0,
+ .regs = pciephy_v4_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS,
+
+ .pipe_clock_rate = 250000000,
+};
+
static const struct qmp_phy_cfg ipq9574_gen3x1_pciephy_cfg = {
.lanes = 1,
@@ -5404,6 +5530,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,glymur-qmp-gen5x4-pcie-phy",
.data = &glymur_qmp_gen5x4_pciephy_cfg,
+ }, {
+ .compatible = "qcom,ipq5210-qmp-gen3x1-pcie-phy",
+ .data = &ipq5210_gen3x1_pciephy_cfg,
}, {
.compatible = "qcom,ipq6018-qmp-pcie-phy",
.data = &ipq6018_pciephy_cfg,
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v3 1/2] dt-bindings: phy: qcom,ipq8074-qmp-pcie: Document the ipq5210 QMP PCIe PHY
From: Varadarajan Narayanan @ 2026-06-10 11:16 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel,
Varadarajan Narayanan
In-Reply-To: <20260610-pcie-phy-v3-0-334011b378d6@oss.qualcomm.com>
Document the PCIe phys on the ipq5210 platform. The 2 lane phy uses the
ipq9574 as fallback. The single lane phy is documented separately.
The ipq5210 has one dual lane and one single lane PCIe phy.
The dual lane phy is similar to the dual lane phy present in ipq9574. Hence
qcom,ipq5210-qmp-gen3x2-pcie-phy is documented with ipq9574's dual lane phy
as fallback compatible.
The single lane phy (qcom,ipq5210-qmp-gen3x1-pcie-phy) is documented as
specific compatible.
Signed-off-by: Varadarajan Narayanan <varadarajan.narayanan@oss.qualcomm.com>
---
Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml
index f60804687412..fc155ad5fa6d 100644
--- a/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml
@@ -17,6 +17,7 @@ properties:
compatible:
oneOf:
- enum:
+ - qcom,ipq5210-qmp-gen3x1-pcie-phy
- qcom,ipq6018-qmp-pcie-phy
- qcom,ipq8074-qmp-gen3-pcie-phy
- qcom,ipq8074-qmp-pcie-phy
@@ -28,6 +29,7 @@ properties:
- const: qcom,ipq9574-qmp-gen3x1-pcie-phy
- items:
- enum:
+ - qcom,ipq5210-qmp-gen3x2-pcie-phy
- qcom,ipq5424-qmp-gen3x2-pcie-phy
- const: qcom,ipq9574-qmp-gen3x2-pcie-phy
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v3 0/2] Enable the QMP PCIe PHY present in Qualcomm ipq5210 SoC
From: Varadarajan Narayanan @ 2026-06-10 11:16 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel,
Varadarajan Narayanan
Document the bindings and update the driver to support
the PCIe phy present in Qualcomm ipq5210 SoC.
v3: Fix commit message for the bindings patch
Remove unused tables from the phy driver (ipq5210_gen3x1_pcie_ep_tx_tbl
and ipq5210_gen3x1_pcie_ep_pcs_tbl)
v2: https://lore.kernel.org/r/20260609-pcie-phy-v2-0-83bc80e79fa6@oss.qualcomm.com
Had incorrectly made both the phys as fallback. The single
lane phy is standalone and double lane uses ipq9574 as
fallback.
v1: https://lore.kernel.org/linux-arm-msm/20260514-pci-phy-v1-0-482429192746@oss.qualcomm.com/
Signed-off-by: Varadarajan Narayanan <varadarajan.narayanan@oss.qualcomm.com>
---
Varadarajan Narayanan (2):
dt-bindings: phy: qcom,ipq8074-qmp-pcie: Document the ipq5210 QMP PCIe PHY
phy: qcom-qmp-pcie: Add support for ipq5210 PCIe phys
.../bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml | 2 +
drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 129 +++++++++++++++++++++
2 files changed, 131 insertions(+)
---
base-commit: a87737435cfa134f9cdcc696ba3080759d04cf72
change-id: 20260609-pcie-phy-99fcf91a02fd
prerequisite-change-id: 20260514-icc-ipq5210-0ab03f3a3e83:v1
prerequisite-patch-id: 0b6145b6635b18fe79fbbff5815041b43778c5ed
prerequisite-patch-id: 924c6ff7baf4283ac7991ee94c803a00fc5cece4
prerequisite-patch-id: c2fe1800fe769dccd37f94c19860a07f979e3c4c
Best regards,
--
Varadarajan Narayanan <varadarajan.narayanan@oss.qualcomm.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH 9/9] phy: qcom-mipi-csi2: accept PHY_QCOM_CSI2_MODE_DPHY phy-cell
From: Ramshouriesh @ 2026-06-10 11:09 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy, Ramshouriesh
In-Reply-To: <20260610-a14-himax-hm1092-v1-0-0c9907da47ed@gmail.com>
qcom_csi2_phy_xlate() validates the phy-cell against the generic
PHY_TYPE_DPHY (10) instead of PHY_QCOM_CSI2_MODE_DPHY (0), so a correct
DPHY request from the camss DTSI is rejected with -EOPNOTSUPP and camss
probe fails with -95.
Include the CSI2 mode header and check the phy-cell against
PHY_QCOM_CSI2_MODE_DPHY.
Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
---
drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
index dfeff863a406..857c54cbaea6 100644
--- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
@@ -3,6 +3,7 @@
* Copyright (c) 2025, Linaro Ltd.
*/
#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/phy-qcom-mipi-csi2.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
@@ -188,7 +189,7 @@ static struct phy *qcom_csi2_phy_xlate(struct device *dev,
{
struct mipi_csi2phy_device *csi2phy = dev_get_drvdata(dev);
- if (args->args[0] != PHY_TYPE_DPHY) {
+ if (args->args[0] != PHY_QCOM_CSI2_MODE_DPHY) {
dev_err(csi2phy->dev, "mode %d -EOPNOTSUPP\n", args->args[0]);
return ERR_PTR(-EOPNOTSUPP);
}
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 8/9] dt-bindings: phy: qcom: add MIPI CSI2 mode constants
From: Ramshouriesh @ 2026-06-10 11:09 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy, Ramshouriesh
In-Reply-To: <20260610-a14-himax-hm1092-v1-0-0c9907da47ed@gmail.com>
The CSI2-PHY binding references <dt-bindings/phy/phy-qcom-mipi-csi2.h>
and consumers (the x1e80100/hamoa camss DTSI) select D-PHY mode with
PHY_QCOM_CSI2_MODE_DPHY, but the v8 CSI2-PHY series does not ship the
header, so any DT that includes it fails to build.
Add the header with the CSI2 mode constants and cover it in MAINTAINERS.
Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
---
MAINTAINERS | 1 +
include/dt-bindings/phy/phy-qcom-mipi-csi2.h | 15 +++++++++++++++
2 files changed, 16 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index ece71732e6dd..a7ee9f0aaaa8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22280,6 +22280,7 @@ S: Maintained
F: Documentation/devicetree/bindings/phy/qcom,*-csi2-phy.yaml
F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.c
F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.h
+F: include/dt-bindings/phy/phy-qcom-mipi-csi2*
QUALCOMM NAND CONTROLLER DRIVER
M: Manivannan Sadhasivam <mani@kernel.org>
diff --git a/include/dt-bindings/phy/phy-qcom-mipi-csi2.h b/include/dt-bindings/phy/phy-qcom-mipi-csi2.h
new file mode 100644
index 000000000000..fa48fd75c58d
--- /dev/null
+++ b/include/dt-bindings/phy/phy-qcom-mipi-csi2.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Qualcomm MIPI CSI2 PHY constants
+ *
+ * Copyright (C) 2026 Linaro Limited
+ */
+
+#ifndef __DT_BINDINGS_PHY_MIPI_CSI2__
+#define __DT_BINDINGS_PHY_MIPI_CSI2__
+
+#define PHY_QCOM_CSI2_MODE_DPHY 0
+#define PHY_QCOM_CSI2_MODE_CPHY 1
+#define PHY_QCOM_CSI2_MODE_SPLIT_DPHY 2
+
+#endif /* __DT_BINDINGS_PHY_MIPI_CSI2__ */
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 7/9] arm64: dts: qcom: hamoa: reorder csiphy power-domains for v8 CSI2-PHY
From: Ramshouriesh @ 2026-06-10 11:09 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy, Ramshouriesh
In-Reply-To: <20260610-a14-himax-hm1092-v1-0-0c9907da47ed@gmail.com>
The v8 phy-qcom-mipi-csi2 binding mandates power-domain-names ordered
"mmcx", "mx" (MMCX first), and its driver reads each domain's required
performance state by index via dev_pm_opp_get_required_pstate(opp, i).
The v3-era camss DTSI listed them "mx", "mmcx" (MXC/MX first), which is
rejected by the v8 binding and, with the v8 driver's
devm_pm_domain_attach_list() + per-index OPP lookup, maps the wrong
pstate to the wrong rail.
Reorder all four csiphy nodes to <MMCX>, <MXC|MX> / "mmcx", "mx". The
second rail stays MXC for csiphy0/1/2 and MX for csiphy4 (the binding
explicitly allows "MXC or MXA" for the second domain); the opp-table
required-opps values are symmetric so they need no change.
Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
---
arch/arm64/boot/dts/qcom/hamoa.dtsi | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi
index 4226db30e244..1200101d7bb7 100644
--- a/arch/arm64/boot/dts/qcom/hamoa.dtsi
+++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi
@@ -5853,10 +5853,10 @@ csiphy0: phy@ace4000 {
interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>;
- power-domains = <&rpmhpd RPMHPD_MXC>,
- <&rpmhpd RPMHPD_MMCX>;
- power-domain-names = "mx",
- "mmcx";
+ power-domains = <&rpmhpd RPMHPD_MMCX>,
+ <&rpmhpd RPMHPD_MXC>;
+ power-domain-names = "mmcx",
+ "mx";
#phy-cells = <1>;
@@ -5876,10 +5876,10 @@ csiphy1: phy@ace6000 {
interrupts = <GIC_SPI 478 IRQ_TYPE_EDGE_RISING>;
- power-domains = <&rpmhpd RPMHPD_MXC>,
- <&rpmhpd RPMHPD_MMCX>;
- power-domain-names = "mx",
- "mmcx";
+ power-domains = <&rpmhpd RPMHPD_MMCX>,
+ <&rpmhpd RPMHPD_MXC>;
+ power-domain-names = "mmcx",
+ "mx";
#phy-cells = <1>;
@@ -5899,10 +5899,10 @@ csiphy2: phy@ace8000 {
interrupts = <GIC_SPI 479 IRQ_TYPE_EDGE_RISING>;
- power-domains = <&rpmhpd RPMHPD_MXC>,
- <&rpmhpd RPMHPD_MMCX>;
- power-domain-names = "mx",
- "mmcx";
+ power-domains = <&rpmhpd RPMHPD_MMCX>,
+ <&rpmhpd RPMHPD_MXC>;
+ power-domain-names = "mmcx",
+ "mx";
#phy-cells = <1>;
@@ -5922,10 +5922,10 @@ csiphy4: phy@acec000 {
interrupts = <GIC_SPI 122 IRQ_TYPE_EDGE_RISING>;
- power-domains = <&rpmhpd RPMHPD_MX>,
- <&rpmhpd RPMHPD_MMCX>;
- power-domain-names = "mx",
- "mmcx";
+ power-domains = <&rpmhpd RPMHPD_MMCX>,
+ <&rpmhpd RPMHPD_MX>;
+ power-domain-names = "mmcx",
+ "mx";
#phy-cells = <1>;
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 6/9] arm64: dts/media: qcom: keep PLL8 out of Purwa camss hot path
From: Ramshouriesh @ 2026-06-10 11:09 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy, Ramshouriesh
In-Reply-To: <20260610-a14-himax-hm1092-v1-0-0c9907da47ed@gmail.com>
cam_cc_pll8 (defined in camcc-x1e80100.c) doesn't latch on Purwa
silicon. "Lucid PLL latch failed. Output may be unstable!" fires from
wait_for_pll() whenever something asks for a PLL8-sourced rate, and
the camera pipeline ends up dead with "Failed to start media
pipeline: -32" even after the qcom,x1p42100-camss compatible is in
place.
PLL8 sneaks into the streaming path via two RCG freq tables: the
slow_ahb RCG defaults to its 64 MHz entry (PLL8-sourced) when CSID
pulls it during csid_set_power, and vfe_lite picks its highest entry
(480 MHz, also PLL8) at streamon.
Fix this from the DT side:
* pin slow_ahb at 80 MHz via assigned-clock-rates in purwa.dtsi so
the RCG is reprogrammed to PLL0_OUT_EVEN at clk-init time and
never reaches PLL8;
* drop the 480 MHz entry from the Purwa vfe_lite clock_rate array
so the driver caps at 400 MHz (PLL0_OUT_ODD).
I went poking at the Qualcomm Windows BSP shipped for the UX3407QA to
see what rates the vendor side actually uses. The AeoB resource blob
at qccamplatform_ext8380/CAMP_{PERF,RES}_MTP.bin lists the camera
clocks Windows enables, and PLL8 isn't referenced once. For CCI in
particular Windows runs at 37.5 MHz off PLL0_OUT_EVEN, not the
30 MHz/PLL8 alternative the Linux driver happens to pick first.
Whether PLL8 is fused off, trust-zone-only, or just unwired on this
SoC I don't know, but treating it as unavailable matches what the
vendor does.
Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
---
arch/arm64/boot/dts/qcom/purwa.dtsi | 12 ++++++++++++
drivers/media/platform/qcom/camss/camss.c | 16 ++++++++--------
2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi
index cee72349da49..5e39355c38d4 100644
--- a/arch/arm64/boot/dts/qcom/purwa.dtsi
+++ b/arch/arm64/boot/dts/qcom/purwa.dtsi
@@ -409,3 +409,15 @@ &tsens3 {
&videocc {
compatible = "qcom,x1p42100-videocc";
};
+
+/*
+ * PLL8 in the camcc-x1e80100 driver fails to lock on Purwa silicon
+ * ("Lucid PLL latch failed"). Several RCGs default to PLL8 as parent
+ * (slow_ahb at 64 MHz, cci_0 at 30 MHz). Pin slow_ahb to the next-best
+ * PLL0-sourced rate (80 MHz) at clock-init time so enabling it does not
+ * try to bring PLL8 up. cci_0 already defaults to 19.2 MHz via TCXO.
+ */
+&camcc {
+ assigned-clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>;
+ assigned-clock-rates = <80000000>;
+};
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 5c9530d52bbd..ca43ff309b26 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -4437,8 +4437,8 @@ static const struct camss_subdev_resources vfe_res_x1e80100[] = {
{ 0 },
{ 0 },
{ 0 },
- { 266666667, 400000000, 480000000 },
- { 266666667, 400000000, 480000000 }, },
+ { 266666667, 400000000 },
+ { 266666667, 400000000 }, },
.reg = { "vfe_lite0" },
.interrupt = { "vfe_lite0" },
.vfe = {
@@ -4460,8 +4460,8 @@ static const struct camss_subdev_resources vfe_res_x1e80100[] = {
{ 0 },
{ 0 },
{ 0 },
- { 266666667, 400000000, 480000000 },
- { 266666667, 400000000, 480000000 }, },
+ { 266666667, 400000000 },
+ { 266666667, 400000000 }, },
.reg = { "vfe_lite1" },
.interrupt = { "vfe_lite1" },
.vfe = {
@@ -4574,8 +4574,8 @@ static const struct camss_subdev_resources vfe_res_x1p42100[] = {
{ 0 },
{ 0 },
{ 0 },
- { 266666667, 400000000, 480000000 },
- { 266666667, 400000000, 480000000 }, },
+ { 266666667, 400000000 },
+ { 266666667, 400000000 }, },
.reg = { "vfe_lite0" },
.interrupt = { "vfe_lite0" },
.vfe = {
@@ -4597,8 +4597,8 @@ static const struct camss_subdev_resources vfe_res_x1p42100[] = {
{ 0 },
{ 0 },
{ 0 },
- { 266666667, 400000000, 480000000 },
- { 266666667, 400000000, 480000000 }, },
+ { 266666667, 400000000 },
+ { 266666667, 400000000 }, },
.reg = { "vfe_lite1" },
.interrupt = { "vfe_lite1" },
.vfe = {
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 5/9] arm64: dts: qcom: x1-asus-zenbook-a14: add HM1092 IR camera and wire cameras to camss
From: Ramshouriesh @ 2026-06-10 11:09 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy, Ramshouriesh
In-Reply-To: <20260610-a14-himax-hm1092-v1-0-0c9907da47ed@gmail.com>
Add the Himax HM1092 mono NIR (Windows-Hello IR) sensor on CSIPHY0,
together with its PM8550 IR illuminator and the pm8010 l4m/l7m camera
rails, and connect both sensors to the CAMSS input ports defined in
hamoa.dtsi.
On Purwa CAMSS exposes two CSIPHYs (0 and 4) and the camss input port
number selects the CSIPHY by index, so the board wiring is:
camss port@0 -> HM1092 (IR, 1 data lane, CSIPHY0)
camss port@1 -> OV02C10 (RGB, 2 data lanes, CSIPHY4)
Each CSIPHY node carries its sensor's D-PHY lane routing in its own
port@0 endpoint, per the qcom,x1e80100-csi2-phy binding: the PHY driver
parses data-lanes from that endpoint at probe time, and its
remote-endpoint must reference an available device for
fwnode_graph_get_endpoint_by_id() to return it, hence each csiphy
port@0 points at its sensor. The CAMSS-to-CSIPHY association itself
comes from the phys/phy-names properties inherited from hamoa.dtsi.
The IR illuminator is a PM8550 flash LED (channel 4) referenced through
the generic "leds" consumer property from video-interface-devices.yaml.
The HM1092 driver strobes it while streaming (700 mA, re-fired within
the 1.28 s hardware safety timeout) so the scene stays lit for IR
face-unlock capture.
Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
---
arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi | 140 ++++++++++++++++++++--
1 file changed, 129 insertions(+), 11 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi b/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
index 388737eaa624..ab8f231cad8d 100644
--- a/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
@@ -8,7 +8,6 @@
#include <dt-bindings/input/gpio-keys.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
-#include <dt-bindings/phy/phy.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
@@ -815,6 +814,20 @@ vreg_l3m_1p8: ldo3 {
regulator-max-microvolt = <1800000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
+
+ vreg_l4m_1p8: ldo4 {
+ regulator-name = "vreg_l4m_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7m_2p9: ldo7 {
+ regulator-name = "vreg_l7m_2p9";
+ regulator-min-microvolt = <2912000>;
+ regulator-max-microvolt = <2912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
};
};
@@ -824,14 +837,19 @@ &camss {
ports {
/*
* port0 => csiphy0
- * port1 => csiphy1
- * port2 => csiphy2
- * port3 => csiphy4
+ * port1 => csiphy4
*/
- port@3 {
- csiphy4_ep: endpoint@4 {
- reg = <4>;
- clock-lanes = <7>;
+ port@0 {
+ camss_csiphy0_inep: endpoint@0 {
+ reg = <0>;
+ data-lanes = <0>;
+ remote-endpoint = <&hm1092_ep>;
+ };
+ };
+
+ port@1 {
+ camss_csiphy4_inep: endpoint@0 {
+ reg = <0>;
data-lanes = <0 1>;
remote-endpoint = <&ov02c10_ep>;
};
@@ -869,18 +887,102 @@ port {
ov02c10_ep: endpoint {
data-lanes = <1 2>;
link-frequencies = /bits/ 64 <400000000>;
- remote-endpoint = <&csiphy4_ep>;
+ remote-endpoint = <&camss_csiphy4_inep>;
};
};
};
};
&csiphy4 {
- vdda-0p8-supply = <&vreg_l2c_0p8>;
+ vdda-0p9-supply = <&vreg_l2c_0p8>;
+ vdda-1p2-supply = <&vreg_l1c_1p2>;
+
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Sensor input: D-PHY lane routing for the OV02C10 */
+ port@0 {
+ reg = <0>;
+ endpoint {
+ data-lanes = <0 1>;
+ remote-endpoint = <&ov02c10_ep>;
+ };
+ };
+ };
+};
+
+&cci0 {
+ status = "okay";
+};
+
+&cci0_i2c0 {
+ /* Himax HM1092 mono NIR sensor (Windows-Hello IR camera) on CSIPHY0 */
+ camera@24 {
+ compatible = "himax,hm1092";
+ reg = <0x24>;
+
+ reset-gpios = <&tlmm 109 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&cam_ir_default>;
+ pinctrl-names = "default";
+
+ clocks = <&camcc CAM_CC_MCLK0_CLK>;
+ assigned-clocks = <&camcc CAM_CC_MCLK0_CLK>;
+ assigned-clock-rates = <24000000>;
+
+ orientation = <0>;
+
+ /* PM8550 IR illuminator, pulsed by the driver while streaming */
+ leds = <&ir_flash>;
+
+ avdd-supply = <&vreg_l7m_2p9>;
+ dvdd-supply = <&vreg_l7m_2p9>;
+ dovdd-supply = <&vreg_l4m_1p8>;
+
+ port {
+ hm1092_ep: endpoint {
+ data-lanes = <1>;
+ link-frequencies = /bits/ 64 <400000000>;
+ remote-endpoint = <&camss_csiphy0_inep>;
+ };
+ };
+ };
+};
+
+&csiphy0 {
+ vdda-0p9-supply = <&vreg_l2c_0p8>;
vdda-1p2-supply = <&vreg_l1c_1p2>;
- phy-type = <PHY_TYPE_DPHY>;
status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Sensor input: D-PHY lane routing for the HM1092 */
+ port@0 {
+ reg = <0>;
+ endpoint {
+ data-lanes = <0>;
+ remote-endpoint = <&hm1092_ep>;
+ };
+ };
+ };
+};
+
+&pm8550_flash {
+ status = "okay";
+
+ ir_flash: led-0 {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_IR>;
+ led-sources = <4>;
+ led-max-microamp = <180000>;
+ flash-max-microamp = <700000>;
+ flash-max-timeout-us = <1280000>;
+ };
};
&i2c0 {
@@ -1384,6 +1486,22 @@ reset-n-pins {
};
};
+ cam_ir_default: cam-ir-default-state {
+ mclk-pins {
+ pins = "gpio96";
+ function = "cam_mclk";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ reset-n-pins {
+ pins = "gpio109";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
edp_reg_en: edp-reg-en-state {
pins = "gpio70";
function = "gpio";
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 4/9] MAINTAINERS: add entry for the Himax HM1092 sensor driver
From: Ramshouriesh @ 2026-06-10 11:09 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy, Ramshouriesh
In-Reply-To: <20260610-a14-himax-hm1092-v1-0-0c9907da47ed@gmail.com>
Add a MAINTAINERS entry covering the Himax HM1092 NIR sensor driver and
its DT binding.
Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index dadc54fe2bc8..ece71732e6dd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11643,6 +11643,14 @@ L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/misc/hisi_hikey_usb.c
+HIMAX HM1092 SENSOR DRIVER
+M: Ramshouriesh <rshouriesh@gmail.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/media/i2c/himax,hm1092.yaml
+F: drivers/media/i2c/hm1092.c
+F: drivers/media/i2c/hm1092_regs.h
+
HIMAX HX83112B TOUCHSCREEN SUPPORT
M: Job Noorman <job@noorman.info>
L: linux-input@vger.kernel.org
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 3/9] media: i2c: hm1092: add Himax HM1092 mono NIR sensor driver
From: Ramshouriesh @ 2026-06-10 11:09 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy, Ramshouriesh
In-Reply-To: <20260610-a14-himax-hm1092-v1-0-0c9907da47ed@gmail.com>
Add a v4l2 subdev driver for the Himax HM1092 monochrome near-IR sensor,
used as the Windows-Hello IR camera on the ASUS Zenbook A14.
The driver also drives the IR illuminator (a PM8550 flash LED referenced
through the generic "leds" property): while streaming it strobes the
illuminator at ~10 Hz, lighting the capture while keeping the average IR
LED power down.
Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
---
drivers/media/i2c/Kconfig | 14 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/hm1092.c | 685 ++++++++++++++++++++++++++++++++++++++++
drivers/media/i2c/hm1092_regs.h | 223 +++++++++++++
4 files changed, 923 insertions(+)
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 5d173e0ecf42..8ee3ee15e9df 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -137,6 +137,20 @@ config VIDEO_HI847
To compile this driver as a module, choose M here: the
module will be called hi847.
+config VIDEO_HM1092
+ tristate "Himax HM1092 sensor support"
+ select V4L2_CCI_I2C
+ help
+ This is a Video4Linux2 sensor driver for the Himax
+ HM1092 1MP mono IR camera used for face authentication
+ on Snapdragon X laptops (ASUS Zenbook A14 etc.).
+
+ Register tables were reverse-engineered from the Qualcomm
+ Chromatix sensor module shipped in the Windows BSP.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hm1092.
+
config VIDEO_IMX111
tristate "Sony IMX111 sensor support"
select V4L2_CCI_I2C
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index e45359efe0e4..6507c173d0fa 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_VIDEO_GC2145) += gc2145.o
obj-$(CONFIG_VIDEO_HI556) += hi556.o
obj-$(CONFIG_VIDEO_HI846) += hi846.o
obj-$(CONFIG_VIDEO_HI847) += hi847.o
+obj-$(CONFIG_VIDEO_HM1092) += hm1092.o
obj-$(CONFIG_VIDEO_I2C) += video-i2c.o
obj-$(CONFIG_VIDEO_IMX111) += imx111.o
obj-$(CONFIG_VIDEO_IMX208) += imx208.o
diff --git a/drivers/media/i2c/hm1092.c b/drivers/media/i2c/hm1092.c
new file mode 100644
index 000000000000..90968ee29d81
--- /dev/null
+++ b/drivers/media/i2c/hm1092.c
@@ -0,0 +1,685 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Himax HM1092 image sensor driver draft.
+ *
+ * Register tables were extracted from Qualcomm Chromatix sensor module
+ * com.qti.sensormodule.hm1092.bin. Keep hm1092_regs.h next to this file, or
+ * fold the generated tables into this source before upstream submission.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/led-class-flash.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/workqueue.h>
+#include <media/v4l2-cci.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+
+#include "hm1092_regs.h"
+
+#define HM1092_LINK_FREQ_400MHZ 400000000ULL
+#define HM1092_MCLK 24000000
+#define HM1092_BITS_PER_SAMPLE 10
+
+#define HM1092_REG_STREAM CCI_REG8(0x0100)
+
+#define HM1092_FLASH_TIMEOUT_US 50000 /* 0.05 s on per pulse */
+#define HM1092_FLASH_REFIRE_MS 100 /* 0.1 s period -> 10 Hz blink */
+
+struct hm1092_mode {
+ u32 width;
+ u32 height;
+ u32 hts;
+ u32 vts;
+};
+
+static const struct hm1092_mode hm1092_mode_560x360 = {
+ .width = 560,
+ .height = 360,
+ .hts = 0x0650,
+ .vts = 0x02ee,
+};
+
+static const char * const hm1092_supply_names[] = {
+ "dovdd",
+ "avdd",
+ "dvdd",
+};
+
+static const char * const hm1092_test_pattern_menu[] = {
+ "Disabled",
+ "Mode 1",
+ "Mode 2",
+ "Mode 3",
+ "Mode 4",
+};
+
+static const s64 hm1092_link_freq_menu[] = {
+ HM1092_LINK_FREQ_400MHZ,
+};
+
+struct hm1092 {
+ struct device *dev;
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct regmap *regmap;
+ struct clk *img_clk;
+ struct gpio_desc *reset;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(hm1092_supply_names)];
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *vblank;
+ u8 mipi_lanes;
+
+ /* Optional IR illuminator driven while streaming (see flash notes). */
+ struct led_classdev_flash *flash;
+ struct delayed_work flash_work;
+};
+
+/*
+ * (Re)arm and fire the flash at full current. The qcom flash controller does an
+ * internal disable+enable on each strobe and the hardware safety-timeout turns
+ * the LED off on its own, so brightness/timeout must be programmed every time or
+ * the re-fire is a no-op. Re-firing well within the timeout keeps the LED lit
+ * continuously and near its (slightly declining) peak brightness.
+ */
+static void hm1092_flash_fire(struct hm1092 *hm1092)
+{
+ struct led_classdev_flash *flash = hm1092->flash;
+
+ /*
+ * Release the controller's flash-current accounting first (a bare
+ * re-strobe is treated as "current still in use" and re-fires at 0 mA),
+ * then re-arm at full current and strobe.
+ */
+ led_set_flash_strobe(flash, false);
+ led_set_flash_brightness(flash, flash->brightness.max);
+ led_set_flash_timeout(flash, HM1092_FLASH_TIMEOUT_US);
+ led_set_flash_strobe(flash, true);
+}
+
+static void hm1092_flash_enable(struct hm1092 *hm1092)
+{
+ if (!hm1092->flash)
+ return;
+
+ hm1092_flash_fire(hm1092);
+ schedule_delayed_work(&hm1092->flash_work,
+ msecs_to_jiffies(HM1092_FLASH_REFIRE_MS));
+}
+
+static void hm1092_flash_disable(struct hm1092 *hm1092)
+{
+ if (!hm1092->flash)
+ return;
+
+ cancel_delayed_work_sync(&hm1092->flash_work);
+ led_set_flash_strobe(hm1092->flash, false);
+}
+
+static void hm1092_flash_work(struct work_struct *work)
+{
+ struct hm1092 *hm1092 =
+ container_of(to_delayed_work(work), struct hm1092, flash_work);
+
+ hm1092_flash_fire(hm1092);
+ schedule_delayed_work(&hm1092->flash_work,
+ msecs_to_jiffies(HM1092_FLASH_REFIRE_MS));
+}
+
+static inline struct hm1092 *to_hm1092(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct hm1092, sd);
+}
+
+static int hm1092_write_regs(struct hm1092 *hm1092,
+ const struct hm1092_reg *regs, unsigned int len)
+{
+ int ret = 0;
+ unsigned int i;
+
+ for (i = 0; i < len; i++) {
+ cci_write(hm1092->regmap, CCI_REG8(regs[i].address),
+ regs[i].val, &ret);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hm1092_set_test_pattern(struct hm1092 *hm1092, int pattern)
+{
+ switch (pattern) {
+ case 0:
+ return hm1092_write_regs(hm1092, hm1092_test_pattern_mode0,
+ ARRAY_SIZE(hm1092_test_pattern_mode0));
+ case 1:
+ return hm1092_write_regs(hm1092, hm1092_test_pattern_mode1,
+ ARRAY_SIZE(hm1092_test_pattern_mode1));
+ case 2:
+ return hm1092_write_regs(hm1092, hm1092_test_pattern_mode2,
+ ARRAY_SIZE(hm1092_test_pattern_mode2));
+ case 3:
+ return hm1092_write_regs(hm1092, hm1092_test_pattern_mode3,
+ ARRAY_SIZE(hm1092_test_pattern_mode3));
+ case 4:
+ return hm1092_write_regs(hm1092, hm1092_test_pattern_mode4,
+ ARRAY_SIZE(hm1092_test_pattern_mode4));
+ default:
+ return -EINVAL;
+ }
+}
+
+static int hm1092_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct hm1092 *hm1092 = container_of(ctrl->handler, struct hm1092,
+ ctrl_handler);
+ int ret = 0;
+
+ if (!pm_runtime_get_if_in_use(hm1092->dev))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_TEST_PATTERN:
+ ret = hm1092_set_test_pattern(hm1092, ctrl->val);
+ break;
+ case V4L2_CID_ANALOGUE_GAIN:
+ case V4L2_CID_EXPOSURE:
+ /* TODO: write to the sensor's exposure/gain registers once
+ * we know which Chromatix middle*Addr fields point at them.
+ */
+ ret = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ pm_runtime_put(hm1092->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops hm1092_ctrl_ops = {
+ .s_ctrl = hm1092_set_ctrl,
+};
+
+static int hm1092_init_controls(struct hm1092 *hm1092)
+{
+ struct v4l2_ctrl_handler *ctrl_hdlr = &hm1092->ctrl_handler;
+ const struct hm1092_mode *mode = &hm1092_mode_560x360;
+ struct v4l2_fwnode_device_properties props;
+ s64 hblank, pixel_rate;
+ int ret;
+
+ v4l2_ctrl_handler_init(ctrl_hdlr, 6);
+
+ hm1092->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
+ &hm1092_ctrl_ops,
+ V4L2_CID_LINK_FREQ,
+ 0, 0,
+ hm1092_link_freq_menu);
+ if (hm1092->link_freq)
+ hm1092->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ pixel_rate = div_u64(HM1092_LINK_FREQ_400MHZ * 2 * hm1092->mipi_lanes,
+ HM1092_BITS_PER_SAMPLE);
+ hm1092->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &hm1092_ctrl_ops,
+ V4L2_CID_PIXEL_RATE, 0,
+ pixel_rate, 1, pixel_rate);
+
+ hblank = mode->hts - mode->width;
+ hm1092->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &hm1092_ctrl_ops,
+ V4L2_CID_HBLANK, hblank, hblank, 1,
+ hblank);
+ if (hm1092->hblank)
+ hm1092->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ hm1092->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &hm1092_ctrl_ops,
+ V4L2_CID_VBLANK,
+ mode->vts - mode->height,
+ 0xffff - mode->height, 1,
+ mode->vts - mode->height);
+ if (hm1092->vblank)
+ hm1092->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ /* Mandatory controls for libcamera. Conservative defaults until we
+ * RE the exposure/gain register address layout from the Chromatix
+ * sensormodule (middleCoarseIntgTimeAddr / shortGlobalGainAddr).
+ */
+ v4l2_ctrl_new_std(ctrl_hdlr, &hm1092_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
+ 0x10, 0xff, 1, 0x10);
+ v4l2_ctrl_new_std(ctrl_hdlr, &hm1092_ctrl_ops, V4L2_CID_EXPOSURE,
+ 1, mode->vts - 4, 1, mode->vts - 4);
+
+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &hm1092_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(hm1092_test_pattern_menu) - 1,
+ 0, 0, hm1092_test_pattern_menu);
+
+ ret = v4l2_fwnode_device_parse(hm1092->dev, &props);
+ if (ret)
+ return ret;
+
+ v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &hm1092_ctrl_ops, &props);
+
+ if (ctrl_hdlr->error)
+ return ctrl_hdlr->error;
+
+ hm1092->sd.ctrl_handler = ctrl_hdlr;
+
+ return 0;
+}
+
+static void hm1092_update_pad_format(struct v4l2_mbus_framefmt *fmt)
+{
+ fmt->width = hm1092_mode_560x360.width;
+ fmt->height = hm1092_mode_560x360.height;
+ fmt->code = MEDIA_BUS_FMT_Y10_1X10;
+ fmt->field = V4L2_FIELD_NONE;
+}
+
+static int hm1092_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ u32 pad, u64 streams_mask)
+{
+ struct hm1092 *hm1092 = to_hm1092(sd);
+ int ret;
+
+ ret = pm_runtime_resume_and_get(hm1092->dev);
+ if (ret)
+ return ret;
+
+ ret = hm1092_write_regs(hm1092, hm1092_init_regs,
+ ARRAY_SIZE(hm1092_init_regs));
+ if (ret) {
+ dev_err(hm1092->dev, "failed to write init registers\n");
+ goto out;
+ }
+
+ ret = __v4l2_ctrl_handler_setup(hm1092->sd.ctrl_handler);
+ if (ret)
+ goto out;
+
+ ret = hm1092_write_regs(hm1092, hm1092_start_streaming,
+ ARRAY_SIZE(hm1092_start_streaming));
+ if (ret)
+ dev_err(hm1092->dev, "failed to start streaming\n");
+ else
+ hm1092_flash_enable(hm1092);
+
+out:
+ if (ret)
+ pm_runtime_put(hm1092->dev);
+
+ return ret;
+}
+
+static int hm1092_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ u32 pad, u64 streams_mask)
+{
+ struct hm1092 *hm1092 = to_hm1092(sd);
+ int ret = 0;
+
+ hm1092_flash_disable(hm1092);
+ cci_write(hm1092->regmap, HM1092_REG_STREAM, 0, &ret);
+ pm_runtime_put(hm1092->dev);
+
+ return ret;
+}
+
+static int hm1092_set_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_format *fmt)
+{
+ hm1092_update_pad_format(&fmt->format);
+ *v4l2_subdev_state_get_format(state, fmt->pad) = fmt->format;
+
+ return 0;
+}
+
+static int hm1092_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index)
+ return -EINVAL;
+
+ code->code = MEDIA_BUS_FMT_Y10_1X10;
+
+ return 0;
+}
+
+static int hm1092_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->index)
+ return -EINVAL;
+
+ if (fse->code != MEDIA_BUS_FMT_Y10_1X10)
+ return -EINVAL;
+
+ fse->min_width = hm1092_mode_560x360.width;
+ fse->max_width = hm1092_mode_560x360.width;
+ fse->min_height = hm1092_mode_560x360.height;
+ fse->max_height = hm1092_mode_560x360.height;
+
+ return 0;
+}
+
+static int hm1092_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ hm1092_update_pad_format(v4l2_subdev_state_get_format(state, 0));
+
+ return 0;
+}
+
+static const struct v4l2_subdev_video_ops hm1092_video_ops = {
+ .s_stream = v4l2_subdev_s_stream_helper,
+};
+
+static const struct v4l2_subdev_pad_ops hm1092_pad_ops = {
+ .set_fmt = hm1092_set_format,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .enum_mbus_code = hm1092_enum_mbus_code,
+ .enum_frame_size = hm1092_enum_frame_size,
+ .enable_streams = hm1092_enable_streams,
+ .disable_streams = hm1092_disable_streams,
+};
+
+static const struct v4l2_subdev_ops hm1092_subdev_ops = {
+ .video = &hm1092_video_ops,
+ .pad = &hm1092_pad_ops,
+};
+
+static const struct media_entity_operations hm1092_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static const struct v4l2_subdev_internal_ops hm1092_internal_ops = {
+ .init_state = hm1092_init_state,
+};
+
+static int hm1092_check_hwcfg(struct hm1092 *hm1092)
+{
+ struct v4l2_fwnode_endpoint bus_cfg = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY,
+ };
+ struct device *dev = hm1092->dev;
+ struct fwnode_handle *ep, *fwnode = dev_fwnode(dev);
+ unsigned long link_freq_bitmap;
+ int ret;
+
+ ep = fwnode_graph_get_endpoint_by_id(fwnode, 0, 0, 0);
+ if (!ep)
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "waiting for fwnode graph endpoint\n");
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+ fwnode_handle_put(ep);
+ if (ret)
+ return dev_err_probe(dev, ret, "parsing endpoint failed\n");
+
+ ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies,
+ bus_cfg.nr_of_link_frequencies,
+ hm1092_link_freq_menu,
+ ARRAY_SIZE(hm1092_link_freq_menu),
+ &link_freq_bitmap);
+ if (ret)
+ goto out;
+
+ if (bus_cfg.bus.mipi_csi2.num_data_lanes != 1 &&
+ bus_cfg.bus.mipi_csi2.num_data_lanes != 2) {
+ ret = dev_err_probe(dev, -EINVAL,
+ "unsupported CSI2 data lanes: %u\n",
+ bus_cfg.bus.mipi_csi2.num_data_lanes);
+ goto out;
+ }
+
+ hm1092->mipi_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
+
+out:
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+ return ret;
+}
+
+static int hm1092_get_pm_resources(struct hm1092 *hm1092)
+{
+ unsigned int i;
+
+ hm1092->reset = devm_gpiod_get_optional(hm1092->dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(hm1092->reset))
+ return dev_err_probe(hm1092->dev, PTR_ERR(hm1092->reset),
+ "failed to get reset gpio\n");
+
+ for (i = 0; i < ARRAY_SIZE(hm1092_supply_names); i++)
+ hm1092->supplies[i].supply = hm1092_supply_names[i];
+
+ return devm_regulator_bulk_get(hm1092->dev,
+ ARRAY_SIZE(hm1092_supply_names),
+ hm1092->supplies);
+}
+
+static int hm1092_power_off(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct hm1092 *hm1092 = to_hm1092(sd);
+
+ gpiod_set_value_cansleep(hm1092->reset, 1);
+ regulator_bulk_disable(ARRAY_SIZE(hm1092_supply_names),
+ hm1092->supplies);
+ clk_disable_unprepare(hm1092->img_clk);
+
+ return 0;
+}
+
+static int hm1092_power_on(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct hm1092 *hm1092 = to_hm1092(sd);
+ int ret;
+
+ /*
+ * Sequence reverse-engineered from the Chromatix AeoB powerSetting:
+ * 1. enable all rails (~1 ms ramp per supply)
+ * 2. hold reset asserted
+ * 3. start MCLK and let the sensor clock for ~1 ms
+ * 4. release reset and wait 18 ms for the sensor to come up
+ */
+ ret = regulator_bulk_enable(ARRAY_SIZE(hm1092_supply_names),
+ hm1092->supplies);
+ if (ret)
+ return ret;
+ usleep_range(3000, 3500);
+
+ if (hm1092->reset)
+ gpiod_set_value_cansleep(hm1092->reset, 1);
+
+ ret = clk_prepare_enable(hm1092->img_clk);
+ if (ret) {
+ regulator_bulk_disable(ARRAY_SIZE(hm1092_supply_names),
+ hm1092->supplies);
+ return ret;
+ }
+ usleep_range(1000, 1200);
+
+ if (hm1092->reset)
+ gpiod_set_value_cansleep(hm1092->reset, 0);
+ usleep_range(18000, 19000);
+
+ return 0;
+}
+
+static void hm1092_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct hm1092 *hm1092 = to_hm1092(sd);
+
+ v4l2_async_unregister_subdev(sd);
+ v4l2_subdev_cleanup(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+ pm_runtime_disable(hm1092->dev);
+ if (!pm_runtime_status_suspended(hm1092->dev)) {
+ hm1092_power_off(hm1092->dev);
+ pm_runtime_set_suspended(hm1092->dev);
+ }
+}
+
+/* Optional: grab the IR illuminator flash LED referenced by the "leds" phandle. */
+static int hm1092_get_flash(struct hm1092 *hm1092)
+{
+ struct led_classdev *cdev;
+
+ cdev = devm_of_led_get_optional(hm1092->dev, 0);
+ if (IS_ERR(cdev))
+ return dev_err_probe(hm1092->dev, PTR_ERR(cdev),
+ "failed to get IR illuminator LED\n");
+ if (!cdev)
+ return 0; /* no illuminator wired; capture still works */
+
+ if (!(cdev->flags & LED_DEV_CAP_FLASH)) {
+ dev_warn(hm1092->dev,
+ "'leds' phandle is not a flash LED; IR illuminator disabled\n");
+ return 0;
+ }
+
+ hm1092->flash = lcdev_to_flcdev(cdev);
+ INIT_DELAYED_WORK(&hm1092->flash_work, hm1092_flash_work);
+ dev_dbg(hm1092->dev, "IR illuminator flash linked (max %u uA)\n",
+ hm1092->flash->brightness.max);
+ return 0;
+}
+
+static int hm1092_probe(struct i2c_client *client)
+{
+ struct hm1092 *hm1092;
+ unsigned long freq;
+ int ret;
+
+ hm1092 = devm_kzalloc(&client->dev, sizeof(*hm1092), GFP_KERNEL);
+ if (!hm1092)
+ return -ENOMEM;
+
+ hm1092->dev = &client->dev;
+
+ ret = hm1092_get_flash(hm1092);
+ if (ret)
+ return ret;
+
+ hm1092->img_clk = devm_v4l2_sensor_clk_get(hm1092->dev, NULL);
+ if (IS_ERR(hm1092->img_clk))
+ return dev_err_probe(hm1092->dev, PTR_ERR(hm1092->img_clk),
+ "failed to get imaging clock\n");
+
+ freq = clk_get_rate(hm1092->img_clk);
+ if (freq != HM1092_MCLK)
+ return dev_err_probe(hm1092->dev, -EINVAL,
+ "external clock %lu is not supported\n",
+ freq);
+
+ v4l2_i2c_subdev_init(&hm1092->sd, client, &hm1092_subdev_ops);
+
+ ret = hm1092_check_hwcfg(hm1092);
+ if (ret)
+ return ret;
+
+ ret = hm1092_get_pm_resources(hm1092);
+ if (ret)
+ return ret;
+
+ hm1092->regmap = devm_cci_regmap_init_i2c(client, 16);
+ if (IS_ERR(hm1092->regmap))
+ return PTR_ERR(hm1092->regmap);
+
+ ret = hm1092_power_on(hm1092->dev);
+ if (ret)
+ return dev_err_probe(hm1092->dev, ret, "failed to power on\n");
+
+ ret = hm1092_init_controls(hm1092);
+ if (ret)
+ goto err_power_off;
+
+ hm1092->sd.internal_ops = &hm1092_internal_ops;
+ hm1092->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ hm1092->sd.entity.ops = &hm1092_entity_ops;
+ hm1092->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ hm1092->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_pads_init(&hm1092->sd.entity, 1, &hm1092->pad);
+ if (ret)
+ goto err_ctrls;
+
+ hm1092->sd.state_lock = hm1092->ctrl_handler.lock;
+ ret = v4l2_subdev_init_finalize(&hm1092->sd);
+ if (ret)
+ goto err_entity;
+
+ pm_runtime_set_active(hm1092->dev);
+ pm_runtime_enable(hm1092->dev);
+
+ /*
+ * The HM1092 has no async sub-devices: no privacy LED, no lens, and
+ * its IR illuminator is a directly-driven led-class-flash (see
+ * hm1092_get_flash()), not a v4l2-flash subdev. Register the plain
+ * subdev rather than v4l2_async_register_subdev_sensor(), whose
+ * automatic privacy-LED lookup would otherwise reject the "leds"
+ * phandle that points at the illuminator.
+ */
+ ret = v4l2_async_register_subdev(&hm1092->sd);
+ if (ret)
+ goto err_subdev;
+
+ pm_runtime_idle(hm1092->dev);
+ return 0;
+
+err_subdev:
+ pm_runtime_disable(hm1092->dev);
+ pm_runtime_set_suspended(hm1092->dev);
+ v4l2_subdev_cleanup(&hm1092->sd);
+err_entity:
+ media_entity_cleanup(&hm1092->sd.entity);
+err_ctrls:
+ v4l2_ctrl_handler_free(hm1092->sd.ctrl_handler);
+err_power_off:
+ hm1092_power_off(hm1092->dev);
+
+ return ret;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(hm1092_pm_ops, hm1092_power_off,
+ hm1092_power_on, NULL);
+
+static const struct of_device_id hm1092_of_match[] = {
+ { .compatible = "himax,hm1092" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, hm1092_of_match);
+
+static struct i2c_driver hm1092_i2c_driver = {
+ .driver = {
+ .name = "hm1092",
+ .pm = pm_sleep_ptr(&hm1092_pm_ops),
+ .of_match_table = hm1092_of_match,
+ },
+ .probe = hm1092_probe,
+ .remove = hm1092_remove,
+};
+
+module_i2c_driver(hm1092_i2c_driver);
+
+MODULE_DESCRIPTION("Himax HM1092 sensor driver draft");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/hm1092_regs.h b/drivers/media/i2c/hm1092_regs.h
new file mode 100644
index 000000000000..4df2d5b49d81
--- /dev/null
+++ b/drivers/media/i2c/hm1092_regs.h
@@ -0,0 +1,223 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* HM1092 register tables extracted from Qualcomm Chromatix sensor module.
+ * Source: com.qti.sensormodule.hm1092.bin
+ * Generator: hm1092-re/gen_hm1092_regs.py
+ * DO NOT HAND EDIT — regenerate from the bin.
+ */
+
+struct hm1092_reg {
+ u16 address;
+ u8 val;
+};
+
+static const struct hm1092_reg hm1092_init_regs[] = {
+ { 0x0103, 0x00 },
+ { 0x030a, 0x05 },
+ { 0x030d, 0x0c },
+ { 0x030f, 0x5a },
+ { 0x0307, 0x00 },
+ { 0x0309, 0x01 },
+ { 0x0387, 0x01 },
+ { 0x0100, 0x02 },
+ { 0x4265, 0x02 },
+ { 0x4002, 0x2b },
+ { 0x4001, 0x00 },
+ { 0x0101, 0x03 },
+ { 0x4024, 0x40 },
+ { 0x0203, 0xbe },
+ { 0x0202, 0x00 },
+ { 0x0341, 0xee },
+ { 0x0340, 0x02 },
+ { 0x0343, 0x50 },
+ { 0x0342, 0x06 },
+ { 0x0345, 0x30 },
+ { 0x0344, 0x00 },
+ { 0x0349, 0xad },
+ { 0x0348, 0x04 },
+ { 0x0347, 0x08 },
+ { 0x0346, 0x00 },
+ { 0x034b, 0xd5 },
+ { 0x034a, 0x02 },
+ { 0x5015, 0xb3 },
+ { 0x0350, 0x53 },
+ { 0x0361, 0x30 },
+ { 0x0360, 0x00 },
+ { 0x034d, 0x30 },
+ { 0x034c, 0x02 },
+ { 0x034f, 0x68 },
+ { 0x034e, 0x01 },
+ { 0x0390, 0x03 },
+ { 0x0383, 0x00 },
+ { 0x0387, 0x10 },
+ { 0x50dd, 0x01 },
+ { 0x50cb, 0x21 },
+ { 0x5005, 0x28 },
+ { 0x5004, 0x40 },
+ { 0x5007, 0x28 },
+ { 0x5006, 0x40 },
+ { 0x5011, 0x00 },
+ { 0x501d, 0x4c },
+ { 0x5013, 0x03 },
+ { 0x4131, 0x01 },
+ { 0x5283, 0x03 },
+ { 0x5282, 0xff },
+ { 0x5010, 0x20 },
+ { 0x4132, 0x20 },
+ { 0x50d5, 0xe0 },
+ { 0x50d7, 0x12 },
+ { 0x50bb, 0x14 },
+ { 0x50b7, 0x00 },
+ { 0x50b9, 0xff },
+ { 0x50b8, 0x70 },
+ { 0x50ba, 0xff },
+ { 0x50fa, 0x02 },
+ { 0x50b4, 0x00 },
+ { 0x50a2, 0x0b },
+ { 0x50ad, 0x07 },
+ { 0x50ac, 0x24 },
+ { 0x50af, 0x40 },
+ { 0x50ae, 0x20 },
+ { 0x50ab, 0x07 },
+ { 0x50aa, 0x22 },
+ { 0x50a7, 0x00 },
+ { 0x50a6, 0x00 },
+ { 0x5099, 0x11 },
+ { 0x509b, 0x03 },
+ { 0x50b3, 0x04 },
+ { 0x50a0, 0x30 },
+ { 0x5098, 0x00 },
+ { 0x52f2, 0x53 },
+ { 0x5209, 0x0c },
+ { 0x5216, 0x02 },
+ { 0x521e, 0x01 },
+ { 0x50e8, 0x00 },
+ { 0x5200, 0x60 },
+ { 0x5202, 0x00 },
+ { 0x5201, 0x80 },
+ { 0x5203, 0x01 },
+ { 0x5208, 0x0b },
+ { 0x520d, 0x40 },
+ { 0x520c, 0x15 },
+ { 0x5215, 0x04 },
+ { 0x50ea, 0x74 },
+ { 0x5214, 0x28 },
+ { 0x5218, 0x07 },
+ { 0x5217, 0x01 },
+ { 0x0310, 0x00 },
+ { 0x4b31, 0x06 },
+ { 0x4b3b, 0x02 },
+ { 0x4b45, 0x01 },
+ { 0x4b44, 0x0c },
+ { 0x4b47, 0x00 },
+ { 0x5101, 0x13 },
+ { 0x5100, 0x03 },
+ { 0x5103, 0x33 },
+ { 0x5102, 0x23 },
+ { 0x5105, 0x42 },
+ { 0x5104, 0x43 },
+ { 0x5106, 0x40 },
+ { 0x5119, 0x00 },
+ { 0x5118, 0x00 },
+ { 0x511b, 0x00 },
+ { 0x511a, 0x00 },
+ { 0x511d, 0x00 },
+ { 0x511c, 0x00 },
+ { 0x511e, 0x00 },
+ { 0x5131, 0x23 },
+ { 0x5130, 0x13 },
+ { 0x5133, 0x43 },
+ { 0x5132, 0x33 },
+ { 0x5135, 0x40 },
+ { 0x5134, 0x42 },
+ { 0x5136, 0x40 },
+ { 0x5149, 0x01 },
+ { 0x5148, 0x01 },
+ { 0x514b, 0x01 },
+ { 0x514a, 0x01 },
+ { 0x514d, 0x01 },
+ { 0x514c, 0x01 },
+ { 0x514e, 0x01 },
+ { 0x51c0, 0x00 },
+ { 0x51c6, 0x00 },
+ { 0x51cc, 0x00 },
+ { 0x51d2, 0x00 },
+ { 0x51d8, 0x00 },
+ { 0x51c1, 0x81 },
+ { 0x51c7, 0x81 },
+ { 0x51cd, 0x81 },
+ { 0x51d3, 0x81 },
+ { 0x51d9, 0x81 },
+ { 0x51c2, 0xec },
+ { 0x51c8, 0xec },
+ { 0x51ce, 0xec },
+ { 0x51d4, 0xec },
+ { 0x51da, 0xec },
+ { 0x51c3, 0x00 },
+ { 0x51c9, 0x00 },
+ { 0x51cf, 0x00 },
+ { 0x51d5, 0x00 },
+ { 0x51db, 0x00 },
+ { 0x51c4, 0x55 },
+ { 0x51ca, 0x55 },
+ { 0x51d0, 0x54 },
+ { 0x51d6, 0x53 },
+ { 0x51dc, 0x53 },
+ { 0x51c5, 0x44 },
+ { 0x51cb, 0x24 },
+ { 0x51d1, 0x24 },
+ { 0x51d7, 0x14 },
+ { 0x51dd, 0x14 },
+ { 0x51e0, 0x09 },
+ { 0x51e2, 0x04 },
+ { 0x51e4, 0x08 },
+ { 0x51e6, 0x08 },
+ { 0x51e1, 0x03 },
+ { 0x51e3, 0x03 },
+ { 0x51e5, 0x07 },
+ { 0x51e8, 0x04 },
+ { 0x51e7, 0x07 },
+ { 0x51e9, 0x46 },
+ { 0x51eb, 0x62 },
+ { 0x51ea, 0x43 },
+ { 0x51ed, 0x00 },
+ { 0x51ec, 0x61 },
+ { 0x51ee, 0x00 },
+ { 0x5206, 0x80 },
+ { 0x3110, 0x02 },
+ { 0x3704, 0x02 },
+ { 0x3704, 0x02 },
+ { 0x4b20, 0x9e },
+ { 0x4b18, 0x00 },
+ { 0x4b3e, 0x00 },
+ { 0x4b0e, 0x0e },
+ { 0x4800, 0xac },
+ { 0x0104, 0x01 },
+ { 0x0104, 0x00 },
+ { 0x4801, 0xae },
+ { 0x0000, 0x00 },
+ { 0x0037, 0x30 },
+};
+
+static const struct hm1092_reg hm1092_start_streaming[] = {
+ { 0x0100, 0x01 },
+};
+
+static const struct hm1092_reg hm1092_test_pattern_mode0[] = {
+ { 0x0601, 0x00 },
+};
+
+static const struct hm1092_reg hm1092_test_pattern_mode1[] = {
+ { 0x0601, 0x01 },
+};
+
+static const struct hm1092_reg hm1092_test_pattern_mode2[] = {
+ { 0x0601, 0x02 },
+};
+
+static const struct hm1092_reg hm1092_test_pattern_mode3[] = {
+ { 0x0601, 0x03 },
+};
+
+static const struct hm1092_reg hm1092_test_pattern_mode4[] = {
+ { 0x0601, 0x04 },
+};
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 2/9] media: dt-bindings: Add Himax HM1092 NIR sensor
From: Ramshouriesh @ 2026-06-10 11:09 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy, Ramshouriesh
In-Reply-To: <20260610-a14-himax-hm1092-v1-0-0c9907da47ed@gmail.com>
Add a dt-binding schema for the Himax HM1092 1MP monochrome
near-infrared CMOS sensor, used as the face-authentication IR camera on
Snapdragon X laptops such as the ASUS Zenbook A14. The sensor streams
10-bit RAW over 1 or 2 MIPI CSI-2 data lanes.
The optional generic "leds" property (video-interface-devices.yaml)
associates an IR illuminator flash LED with the sensor, which the
driver strobes while streaming.
Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
---
.../bindings/media/i2c/himax,hm1092.yaml | 118 +++++++++++++++++++++
1 file changed, 118 insertions(+)
diff --git a/Documentation/devicetree/bindings/media/i2c/himax,hm1092.yaml b/Documentation/devicetree/bindings/media/i2c/himax,hm1092.yaml
new file mode 100644
index 000000000000..085001493a20
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/himax,hm1092.yaml
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/himax,hm1092.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Himax HM1092 Monochrome NIR Sensor
+
+maintainers:
+ - Ramshouriesh <rshouriesh@gmail.com>
+
+description:
+ The Himax HM1092 is a 1 megapixel monochrome near-infrared CMOS image
+ sensor with a MIPI CSI-2 interface, commonly used as the IR camera for
+ face authentication on laptops. It supports 10 bit RAW output at
+ 1288x728 over 1 or 2 CSI-2 data lanes. An optional infrared
+ illuminator LED may be associated with the sensor through the generic
+ "leds" property; the driver strobes it while the sensor is streaming
+ so the scene stays lit for IR capture.
+
+allOf:
+ - $ref: /schemas/media/video-interface-devices.yaml#
+
+properties:
+ compatible:
+ const: himax,hm1092
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ avdd-supply:
+ description: Analogue circuit voltage supply.
+
+ dovdd-supply:
+ description: I/O circuit voltage supply.
+
+ dvdd-supply:
+ description: Digital circuit voltage supply.
+
+ reset-gpios:
+ maxItems: 1
+ description: Active low GPIO connected to the XSHUTDOWN pad.
+
+ leds:
+ description:
+ Optional phandle to an infrared illuminator flash LED strobed by
+ the driver while streaming.
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ additionalProperties: false
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ additionalProperties: false
+
+ properties:
+ data-lanes:
+ minItems: 1
+ maxItems: 2
+ link-frequencies: true
+ remote-endpoint: true
+
+ required:
+ - data-lanes
+ - link-frequencies
+ - remote-endpoint
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - port
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ camera@24 {
+ compatible = "himax,hm1092";
+ reg = <0x24>;
+
+ reset-gpios = <&tlmm 109 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cam_ir_default>;
+
+ clocks = <&camcc 1>;
+ assigned-clocks = <&camcc 1>;
+ assigned-clock-rates = <24000000>;
+
+ orientation = <0>;
+
+ leds = <&ir_flash>;
+
+ avdd-supply = <&vreg_l7m_2p9>;
+ dvdd-supply = <&vreg_l7m_2p9>;
+ dovdd-supply = <&vreg_l4m_1p8>;
+
+ port {
+ hm1092_ep: endpoint {
+ data-lanes = <1>;
+ link-frequencies = /bits/ 64 <400000000>;
+ remote-endpoint = <&camss_csiphy0_inep>;
+ };
+ };
+ };
+ };
+...
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 1/9] arm64: dts: qcom: x1-asus-zenbook-a14: Add on OV02C10 RGB sensor on CSIPHY4
From: Ramshouriesh @ 2026-06-10 11:09 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy, Ramshouriesh
In-Reply-To: <20260610-a14-himax-hm1092-v1-0-0c9907da47ed@gmail.com>
From: Aleksandrs Vinarskis <alex@vinarskis.com>
The device uses Omnivision ov02c10 RGB sensor. Reset GPIO, privacy LED
GPIO, LDOs are extracted from decompiled AeoB files.
Signed-off-by: Aleksandrs Vinarskis <alex@vinarskis.com>
Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
---
arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi | 109 +++++++++++++++++++++-
1 file changed, 105 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi b/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
index 66d566808f58..388737eaa624 100644
--- a/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi
@@ -8,6 +8,7 @@
#include <dt-bindings/input/gpio-keys.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
+#include <dt-bindings/phy/phy.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
@@ -108,14 +109,11 @@ leds {
pinctrl-0 = <&cam_indicator_en>;
pinctrl-names = "default";
- led-camera-indicator {
- label = "white:camera-indicator";
+ privacy_led: privacy-led {
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_WHITE>;
gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "none";
default-state = "off";
- /* Reuse as a panic indicator until we get a "camera on" trigger */
panic-indicator;
};
};
@@ -546,6 +544,13 @@ vreg_l6b_1p8: ldo6 {
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
+ vreg_l7b_2p8: ldo7 {
+ regulator-name = "vreg_l7b_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
vreg_l8b_3p0: ldo8 {
regulator-name = "vreg_l8b_3p0";
regulator-min-microvolt = <3072000>;
@@ -796,6 +801,86 @@ vreg_l3j_0p8: ldo3 {
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
};
+
+ regulators-8 {
+ compatible = "qcom,pm8010-rpmh-regulators";
+ qcom,pmic-id = "m";
+
+ vdd-l3-l4-supply = <&vreg_s4c_1p8>;
+ vdd-l7-supply = <&vreg_bob1>;
+
+ vreg_l3m_1p8: ldo3 {
+ regulator-name = "vreg_l3m_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&camss {
+ status = "okay";
+
+ ports {
+ /*
+ * port0 => csiphy0
+ * port1 => csiphy1
+ * port2 => csiphy2
+ * port3 => csiphy4
+ */
+ port@3 {
+ csiphy4_ep: endpoint@4 {
+ reg = <4>;
+ clock-lanes = <7>;
+ data-lanes = <0 1>;
+ remote-endpoint = <&ov02c10_ep>;
+ };
+ };
+ };
+};
+
+&cci1 {
+ status = "okay";
+};
+
+&cci1_i2c1 {
+ camera@36 {
+ compatible = "ovti,ov02c10";
+ reg = <0x36>;
+
+ reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&cam_rgb_default>;
+ pinctrl-names = "default";
+
+ leds = <&privacy_led>;
+ led-names = "privacy";
+
+ clocks = <&camcc CAM_CC_MCLK4_CLK>;
+ assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ orientation = <0>;
+
+ avdd-supply = <&vreg_l7b_2p8>;
+ dvdd-supply = <&vreg_l7b_2p8>;
+ dovdd-supply = <&vreg_l3m_1p8>;
+
+ port {
+ ov02c10_ep: endpoint {
+ data-lanes = <1 2>;
+ link-frequencies = /bits/ 64 <400000000>;
+ remote-endpoint = <&csiphy4_ep>;
+ };
+ };
+ };
+};
+
+&csiphy4 {
+ vdda-0p8-supply = <&vreg_l2c_0p8>;
+ vdda-1p2-supply = <&vreg_l1c_1p2>;
+ phy-type = <PHY_TYPE_DPHY>;
+
+ status = "okay";
};
&i2c0 {
@@ -1283,6 +1368,22 @@ cam_indicator_en: cam-indicator-en-state {
bias-disable;
};
+ cam_rgb_default: cam-rgb-default-state {
+ mclk-pins {
+ pins = "gpio100";
+ function = "cam_aon";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ reset-n-pins {
+ pins = "gpio237";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
edp_reg_en: edp-reg-en-state {
pins = "gpio70";
function = "gpio";
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 0/9] media/arm64: HM1092 IR camera and ASUS Zenbook A14 (X1P42100) camera support
From: Ramshouriesh @ 2026-06-10 11:09 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Mauro Carvalho Chehab, Bryan O'Donoghue,
Vladimir Zapolskiy, Loic Poulain, Bryan O'Donoghue,
Vinod Koul, Neil Armstrong
Cc: Aleksandrs Vinarskis, linux-arm-msm, devicetree, linux-kernel,
linux-media, linux-phy, Ramshouriesh
The ASUS Zenbook A14 (Qualcomm X1P42100, "Purwa") has two front cameras
behind the SoC CAMSS: an OV02C10 RGB sensor and a Himax HM1092 mono NIR
sensor used for face unlock. This series adds a driver for the HM1092 and
the device tree to wire both sensors up on the A14.
The HM1092 binding, driver and MAINTAINERS entry do not depend on the
rest of the series and can go through the media tree on their own.
The remaining DTS and PHY patches are the A14 camera enablement. They sit
on top of several series that are not in mainline yet, listed below. With
those applied the series builds on next-20260609: the A14 dtb and every
module it touches (hm1092, qcom-camss including csiphy, and the
qcom-mipi-csi2 phy) compile and work: both sensors probe and stream
frames on the A14.
Prerequisites, in the order they apply:
1. phy: dphy: Extend phy_configure_opts_mipi_dphy to support position
and polarity (Bryan O'Donoghue, v1)
https://lore.kernel.org/all/20260325-dphy-params-extension-v1-0-c6df5599284a@linaro.org/
2. clk: qcom: videocc and camcc for X1P42100 (Jagadeesh Kona, v5)
https://lore.kernel.org/all/20260507-purwa-videocc-camcc-v5-0-fc3af4130282@oss.qualcomm.com/
3. phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver (Bryan O'Donoghue, v8)
https://lore.kernel.org/all/20260523-x1e-csi2-phy-v8-0-a85668459521@linaro.org/
4. media: dt-bindings and PHY updates for CAMSS on x1e80100 (Bryan O'Donoghue, v11)
https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-0-5b93415be6dd@linaro.org/
5. arm64: dts: qcom: x1e/Hamoa camera DTSI (Bryan O'Donoghue, v3)
https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-0-1d5a9306116a@linaro.org/
6. media: qcom: camss: Add support for X1P42100 camss (Wenmeng Liu, v2)
https://lore.kernel.org/all/20260511-purwa_camss-v2-0-22608ab9126c@oss.qualcomm.com/
From the videocc/camcc series only the CAMCC block (patch 6/6) is still
needed; its clock drivers and bindings are already in linux-next. That
patch adds the camcc node and sets the Purwa camcc and videocc compatibles.
From the x1e/Hamoa camera DTSI series only the CCI and CAMSS-block patches
are needed; its CAMCC block duplicates the videocc/camcc series, and the
x1e80100 board patches do not apply to the A14.
Patch 1 adds the OV02C10 node. It is Aleksandrs Vinarskis' work, carried
here with his Signed-off-by so the A14 camera support stays one chain.
Signed-off-by: Ramshouriesh <rshouriesh@gmail.com>
---
Aleksandrs Vinarskis (1):
arm64: dts: qcom: x1-asus-zenbook-a14: Add on OV02C10 RGB sensor on CSIPHY4
Ramshouriesh (8):
media: dt-bindings: Add Himax HM1092 NIR sensor
media: i2c: hm1092: add Himax HM1092 mono NIR sensor driver
MAINTAINERS: add entry for the Himax HM1092 sensor driver
arm64: dts: qcom: x1-asus-zenbook-a14: add HM1092 IR camera and wire cameras to camss
arm64: dts/media: qcom: keep PLL8 out of Purwa camss hot path
arm64: dts: qcom: hamoa: reorder csiphy power-domains for v8 CSI2-PHY
dt-bindings: phy: qcom: add MIPI CSI2 mode constants
phy: qcom-mipi-csi2: accept PHY_QCOM_CSI2_MODE_DPHY phy-cell
.../bindings/media/i2c/himax,hm1092.yaml | 118 ++++
MAINTAINERS | 9 +
arch/arm64/boot/dts/qcom/hamoa.dtsi | 32 +-
arch/arm64/boot/dts/qcom/purwa.dtsi | 12 +
arch/arm64/boot/dts/qcom/x1-asus-zenbook-a14.dtsi | 227 ++++++-
drivers/media/i2c/Kconfig | 14 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/hm1092.c | 685 +++++++++++++++++++++
drivers/media/i2c/hm1092_regs.h | 223 +++++++
drivers/media/platform/qcom/camss/camss.c | 16 +-
drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 3 +-
include/dt-bindings/phy/phy-qcom-mipi-csi2.h | 15 +
12 files changed, 1326 insertions(+), 29 deletions(-)
---
base-commit: 49e02880ec0a8c378e811bc9d85da188d7c6204c
change-id: 20260609-a14-himax-hm1092-bbcbe0229afe
prerequisite-message-id: <20260325-dphy-params-extension-v1-0-c6df5599284a@linaro.org>
prerequisite-patch-id: 471e9403130bb3e65cea1d2365d75ef664662306
prerequisite-patch-id: 075fa72fba3c4f51138b88972e6a5e240038d90c
prerequisite-patch-id: 4edca361ad7d370a338641d1ebb5ca65b114a244
prerequisite-patch-id: 32dd1b55ba678d00088b376e33e12d9da6241aca
prerequisite-patch-id: 24424189b11acee204622997908d85a0efbb2503
prerequisite-message-id: <20260523-x1e-csi2-phy-v8-0-a85668459521@linaro.org>
prerequisite-patch-id: dc660c63d4382e84af51241381727954bd5ed013
prerequisite-patch-id: 237410e8df475d80bede4590288b6b053b1483e5
prerequisite-message-id: <20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-0-5b93415be6dd@linaro.org>
prerequisite-patch-id: 6e8e67cd3ab96a602971bbeeb7dfdeaf3f1426a2
prerequisite-patch-id: bbf431fcabc17c30fa5e804eb4accb8275198b37
prerequisite-patch-id: a7fbea14628b62a8de096dea420473b283010aba
prerequisite-patch-id: b6b6c4e7a5818e1b93fe2758902bd32d2be48509
prerequisite-patch-id: 4f11e3d079a484008a03ce750952d6e2933c0253
prerequisite-patch-id: 5f5504fd7b5eee72c3fb8c045fa57219fd2f0456
prerequisite-patch-id: 570b65b326f4c684d813f6ebeda152378dc2a47f
prerequisite-patch-id: bc5b9321c124abd961ae1f60610dc46701dc80ac
prerequisite-patch-id: 6d36feaa3a210039f87ea47aa74423a670260fb6
prerequisite-message-id: <20260511-purwa_camss-v2-0-22608ab9126c@oss.qualcomm.com>
prerequisite-patch-id: 9430f9db2ca3486da39606aa806db3c1973ad2d1
prerequisite-patch-id: d90c86fbd38851530f9480562647703c32a86a91
prerequisite-patch-id: baa498638bf0da1bdc25a3c5e827c351d3b78e79
Best regards,
--
Ramshouriesh <rshouriesh@gmail.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH v2] dt-bindings: phy: sc8280xp-qmp-pcie: Disallow bifurcation register on Purwa
From: Konrad Dybcio @ 2026-06-10 9:45 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel,
Krzysztof Kozlowski, YijieYang, Konrad Dybcio
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Neither of the two Gen4x4 PHYs found on Purwa supports bifurcation.
The PHY is however physically laid out as if it were to, since there
are two separate ports (A/B).
Split out a new if-then block to un-require the bifurcation register
handle to squash this warning:
purwa-iot-evk.dtb: phy@1bd4000 (qcom,x1p42100-qmp-gen4x4-pcie-phy): 'qcom,4ln-config-sel' is a required property
Fixes: 2e1ffd4c1805 ("dt-bindings: phy: qcom,qmp-pcie: Add X1P42100 PCIe Gen4x4 PHY")
Reported-by: Rob Herring <robh@kernel.org>
Closes: https://lore.kernel.org/linux-arm-msm/176857775469.1631885.16133311938753588148.robh@kernel.org/
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
Changes in v2:
- Rebase
- Don't drop the mention of the warning, as it now actually exists in
the tree..
- Link to v1: https://lore.kernel.org/r/20260119-topic-purwa_phy_shutup_warning-v1-1-997a692b31c6@oss.qualcomm.com
To: Vinod Koul <vkoul@kernel.org>
To: Neil Armstrong <neil.armstrong@linaro.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Cc: linux-arm-msm@vger.kernel.org
Cc: linux-phy@lists.infradead.org
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
.../devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
index 3a35120a77ec..431e8cb5df84 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
@@ -136,13 +136,22 @@ allOf:
items:
- description: port a
- description: port b
- required:
- - qcom,4ln-config-sel
else:
properties:
reg:
maxItems: 1
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sc8280xp-qmp-gen3x4-pcie-phy
+ - qcom,x1e80100-qmp-gen4x4-pcie-phy
+ then:
+ required:
+ - qcom,4ln-config-sel
+
- if:
properties:
compatible:
---
base-commit: 49e02880ec0a8c378e811bc9d85da188d7c6204c
change-id: 20260119-topic-purwa_phy_shutup_warning-891e8aab29f2
Best regards,
--
Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* Re: [PATCH v2 1/2] dt-bindings: phy: qcom,ipq8074-qmp-pcie: Document the ipq5210 QMP PCIe PHY
From: Krzysztof Kozlowski @ 2026-06-10 7:59 UTC (permalink / raw)
To: Varadarajan Narayanan
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-arm-msm, linux-phy, devicetree, linux-kernel
In-Reply-To: <20260609-pcie-phy-v2-1-83bc80e79fa6@oss.qualcomm.com>
On Tue, Jun 09, 2026 at 02:52:12PM +0530, Varadarajan Narayanan wrote:
> Document the PCIe phys on the ipq5210 platform. The 2 lane phy uses the
> ipq9574 as fallback. The single lane phy is documented separately.
What does it mean "separately"? Diffent commit? Explain here the
hardware, compatibility or lack of thereof, not the diff contents.
Best regards,
Krzysztof
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 02/12] clk: thead: th1520-ap: add support for MISC subsys clocks
From: Drew Fustini @ 2026-06-10 4:33 UTC (permalink / raw)
To: Icenowy Zheng
Cc: Guo Ren, Fu Wei, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul, Neil Armstrong,
Greg Kroah-Hartman, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Jisheng Zhang, Philipp Zabel, linux-riscv,
linux-clk, devicetree, linux-kernel, linux-gpio, linux-phy,
linux-usb, Han Gao, Yao Zi
In-Reply-To: <aievi0s-3SO8hV6a@thelio>
On Mon, Jun 08, 2026 at 11:15:39PM -0700, Drew Fustini wrote:
> On Tue, Jun 09, 2026 at 02:01:43PM +0800, Icenowy Zheng wrote:
> > 在 2026-06-08一的 23:00 -0700,Drew Fustini写道:
> > > On Thu, May 07, 2026 at 04:17:00PM +0800, Icenowy Zheng wrote:
> > > > The TH1520 SoC contains a MISC_SUBSYS clock controller, which
> > > > allows
> > > > controlling of USB related clocks and MMC/SD controller AHB bus
> > > > clocks.
> > > >
> > > > Add support for this clock controller, in order to enable USB
> > > > support.
> > > >
> > > > Signed-off-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
> > > > ---
> > > > drivers/clk/thead/clk-th1520-ap.c | 64
> > > > +++++++++++++++++++++++++++++++
> > > > 1 file changed, 64 insertions(+)
> > > >
> > > > diff --git a/drivers/clk/thead/clk-th1520-ap.c
> > > > b/drivers/clk/thead/clk-th1520-ap.c
> > > > index 3a6847f1c950f..24f785f0b329a 100644
> > > > --- a/drivers/clk/thead/clk-th1520-ap.c
> > > > +++ b/drivers/clk/thead/clk-th1520-ap.c
> > > [...]
> > > > @@ -1609,6 +1663,12 @@ static int th1520_clk_probe(struct
> > > > platform_device *pdev)
> > > > return ret;
> > > > }
> > > >
> > > > + if (plat_data == &th1520_ap_platdata) {
> > > > + ret = devm_clk_hw_register(dev,
> > > > &usb_suspend_div_clk.hw);
> > > > + if (ret)
> > > > + return ret;
> > > > + }
> > >
> > > Should usb_suspend_div_clk.hw instead be registered under
> > > 'if (plat_data == &th1520_ap_platdata)'?
> >
> > Do you mean misc_platdata?
> >
> > Yes, this is an copy-n-paste error that deserves a fix.
>
> Hah, yes, I also had a typo :)
Assuming that gets fixed in the next rev:
Reviewed-by: Drew Fusini <fustini@kernel.org>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v8 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Dmitry Baryshkov @ 2026-06-09 22:30 UTC (permalink / raw)
To: Vijay Kumar Tumati
Cc: Konrad Dybcio, Bryan O'Donoghue, Vladimir Zapolskiy,
Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong,
linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel
In-Reply-To: <04479989-8aca-46bd-8153-1dd033f1fdd5@oss.qualcomm.com>
On Tue, Jun 09, 2026 at 12:20:56PM -0700, Vijay Kumar Tumati wrote:
>
>
> On 6/9/2026 6:56 AM, Konrad Dybcio wrote:
> > On 6/4/26 11:06 AM, Bryan O'Donoghue wrote:
> > > On 04/06/2026 09:46, Vladimir Zapolskiy wrote:
> > > > On 6/4/26 03:30, Bryan O'Donoghue wrote:
> > > > > On 04/06/2026 01:07, Vladimir Zapolskiy wrote:
> > > > > > On 6/4/26 00:18, Bryan O'Donoghue wrote:
> > > > > > > On 03/06/2026 21:51, Vladimir Zapolskiy wrote:
> > > > > > > > > Actually, one more thing, Why isn't TITAN TOP GDSC here?>>>> +
> > > > > > > > If CSIPHYs are true subdevices under the umbrella CAMSS device and well
> > > > > > > > described as subnodes, then likely none of power domains are needed
> > [...]
> >
> > > > CCI is not described as a child of CAMSS, here the situation is different.
> > > CCI probably_should_ be a child of CAMSS given the design we are going for here.
> > Yes
> As of now CCI is an independently usable device to configure any I2C slave
> that is connected to it. If it is to become a child of camss, it should be
> self contained, as it is now, and camss may have to become a simple-mfd to
> make the CCI independently probe-able? In which case, we may want to follow
> the same protocol for all other sub devices like PHY. However, if we do not
> have any requirement to use CCI independently (who can confirm this?),
Uno-Q uses CCI as a semi-independent i2c controller. There can be other
similar designs.
> probably, we can stick with devm_of_platform_populate() model with common
> resources at the CAMSS TOP node and sub-device specific resources (only) in
> the child devices.
--
With best wishes
Dmitry
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v8 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Vijay Kumar Tumati @ 2026-06-09 19:20 UTC (permalink / raw)
To: Konrad Dybcio, Bryan O'Donoghue, Vladimir Zapolskiy,
Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong
Cc: linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel
In-Reply-To: <335238ae-c476-40e6-8639-44258fefe988@oss.qualcomm.com>
On 6/9/2026 6:56 AM, Konrad Dybcio wrote:
> On 6/4/26 11:06 AM, Bryan O'Donoghue wrote:
>> On 04/06/2026 09:46, Vladimir Zapolskiy wrote:
>>> On 6/4/26 03:30, Bryan O'Donoghue wrote:
>>>> On 04/06/2026 01:07, Vladimir Zapolskiy wrote:
>>>>> On 6/4/26 00:18, Bryan O'Donoghue wrote:
>>>>>> On 03/06/2026 21:51, Vladimir Zapolskiy wrote:
>>>>>>>> Actually, one more thing, Why isn't TITAN TOP GDSC here?>>>> +
>>>>>>> If CSIPHYs are true subdevices under the umbrella CAMSS device and well
>>>>>>> described as subnodes, then likely none of power domains are needed
> [...]
>
>>> CCI is not described as a child of CAMSS, here the situation is different.
>> CCI probably_should_ be a child of CAMSS given the design we are going for here.
> Yes
As of now CCI is an independently usable device to configure any I2C
slave that is connected to it. If it is to become a child of camss, it
should be self contained, as it is now, and camss may have to become a
simple-mfd to make the CCI independently probe-able? In which case, we
may want to follow the same protocol for all other sub devices like PHY.
However, if we do not have any requirement to use CCI independently (who
can confirm this?), probably, we can stick with
devm_of_platform_populate() model with common resources at the CAMSS TOP
node and sub-device specific resources (only) in the child devices.
Thanks,
Vijay.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v4 phy-next 14/16] dt-bindings: phy: lynx-10g: initial document
From: Conor Dooley @ 2026-06-09 16:26 UTC (permalink / raw)
To: Vladimir Oltean
Cc: linux-phy, Ioana Ciornei, Vinod Koul, Neil Armstrong,
Tanjeff Moos, linux-kernel, Rob Herring, devicetree, Conor Dooley,
Krzysztof Kozlowski
In-Reply-To: <20260608221710.1572971-15-vladimir.oltean@nxp.com>
[-- Attachment #1.1: Type: text/plain, Size: 496 bytes --]
On Tue, Jun 09, 2026 at 01:17:08AM +0300, Vladimir Oltean wrote:
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - fsl,ls1046a-serdes1
> + - fsl,ls1046a-serdes2
> + then:
> + properties:
> + big-endian: true
This should have stayed at the top-level FWIW, and here you would do
then:
required:
- big-endian
else:
properties:
big-endian: false
> + required:
> + - big-endian
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 112 bytes --]
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox