devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Zhi Mao (毛智)" <zhi.mao@mediatek.com>
To: "mchehab@kernel.org" <mchehab@kernel.org>,
	"sakari.ailus@linux.intel.com" <sakari.ailus@linux.intel.com>,
	"angelogioacchino.delregno@collabora.com"
	<angelogioacchino.delregno@collabora.com>,
	"robh+dt@kernel.org" <robh+dt@kernel.org>,
	"krzysztof.kozlowski+dt@linaro.org"
	<krzysztof.kozlowski+dt@linaro.org>
Cc: "heiko@sntech.de" <heiko@sntech.de>,
	"gerald.loacker@wolfvision.net" <gerald.loacker@wolfvision.net>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"yunkec@chromium.org" <yunkec@chromium.org>,
	"linux-mediatek@lists.infradead.org"
	<linux-mediatek@lists.infradead.org>,
	"dan.scally@ideasonboard.com" <dan.scally@ideasonboard.com>,
	"linux-media@vger.kernel.org" <linux-media@vger.kernel.org>,
	"Shengnan Wang (王圣男)" <shengnan.wang@mediatek.com>,
	"hdegoede@redhat.com" <hdegoede@redhat.com>,
	"linus.walleij@linaro.org" <linus.walleij@linaro.org>,
	"andy.shevchenko@gmail.com" <andy.shevchenko@gmail.com>,
	"Yaya Chang (張雅清)" <Yaya.Chang@mediatek.com>,
	"bingbu.cao@intel.com" <bingbu.cao@intel.com>,
	"jacopo.mondi@ideasonboard.com" <jacopo.mondi@ideasonboard.com>,
	"jernej.skrabec@gmail.com" <jernej.skrabec@gmail.com>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	"conor+dt@kernel.org" <conor+dt@kernel.org>,
	Project_Global_Chrome_Upstream_Group
	<Project_Global_Chrome_Upstream_Group@mediatek.com>,
	"10572168@qq.com" <10572168@qq.com>,
	"hverkuil-cisco@xs4all.nl" <hverkuil-cisco@xs4all.nl>,
	"tomi.valkeinen@ideasonboard.com"
	<tomi.valkeinen@ideasonboard.com>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	"matthias.bgg@gmail.com" <matthias.bgg@gmail.com>,
	"laurent.pinchart@ideasonboard.com"
	<laurent.pinchart@ideasonboard.com>,
	"macromorgan@hotmail.com" <macromorgan@hotmail.com>
Subject: Re: [PATCH v4 2/2] media: i2c: Add GC08A3 image sensor driver
Date: Tue, 20 Feb 2024 02:21:21 +0000	[thread overview]
Message-ID: <1a9cb6c04de90cde777e30e15b0bced4c1d002f9.camel@mediatek.com> (raw)
In-Reply-To: <21370bd8-502b-4b4e-8c9b-6d13c60685d5@collabora.com>

Hi AngeloGioacchino,

Thanks for your review.

On Wed, 2024-02-07 at 15:42 +0100, AngeloGioacchino Del Regno wrote:
> Il 04/02/24 07:15, Zhi Mao ha scritto:
> > Add a V4L2 sub-device driver for Galaxycore GC08A3 image sensor.
> > 
> > Signed-off-by: Zhi Mao <zhi.mao@mediatek.com>
> > ---
> >   drivers/media/i2c/Kconfig  |   10 +
> >   drivers/media/i2c/Makefile |    1 +
> >   drivers/media/i2c/gc08a3.c | 1448
> > ++++++++++++++++++++++++++++++++++++
> >   3 files changed, 1459 insertions(+)
> >   create mode 100644 drivers/media/i2c/gc08a3.c
> > 
> > diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> > index 56f276b920ab..e4da68835683 100644
> > --- a/drivers/media/i2c/Kconfig
> > +++ b/drivers/media/i2c/Kconfig
> > @@ -70,6 +70,16 @@ config VIDEO_GC0308
> >   	  To compile this driver as a module, choose M here: the
> >   	  module will be called gc0308.
> >   
> > +config VIDEO_GC08A3
> > +	tristate "GalaxyCore gc08a3 sensor support"
> > +	select V4L2_CCI_I2C
> > +	help
> > +	  This is a Video4Linux2 sensor driver for the GalaxyCore
> > gc08a3
> > +	  camera.
> > +
> > +	  To compile this driver as a module, choose M here: the
> > +	  module will be called gc08a3.
> > +
> >   config VIDEO_GC2145
> >   	select V4L2_CCI_I2C
> >   	tristate "GalaxyCore GC2145 sensor support"
> > diff --git a/drivers/media/i2c/Makefile
> > b/drivers/media/i2c/Makefile
> > index dfbe6448b549..b82e99ca7578 100644
> > --- a/drivers/media/i2c/Makefile
> > +++ b/drivers/media/i2c/Makefile
> > @@ -38,6 +38,7 @@ obj-$(CONFIG_VIDEO_DW9768) += dw9768.o
> >   obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
> >   obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/
> >   obj-$(CONFIG_VIDEO_GC0308) += gc0308.o
> > +obj-$(CONFIG_VIDEO_GC08A3) += gc08a3.o
> >   obj-$(CONFIG_VIDEO_GC2145) += gc2145.o
> >   obj-$(CONFIG_VIDEO_HI556) += hi556.o
> >   obj-$(CONFIG_VIDEO_HI846) += hi846.o
> > diff --git a/drivers/media/i2c/gc08a3.c
> > b/drivers/media/i2c/gc08a3.c
> > new file mode 100644
> > index 000000000000..3fc7fffb815c
> > --- /dev/null
> > +++ b/drivers/media/i2c/gc08a3.c
> > @@ -0,0 +1,1448 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * gc08a3.c - gc08a3 sensor driver
> > + *
> > + * Copyright 2023 MediaTek
> > + *
> > + * Zhi Mao <zhi.mao@mediatek.com>
> > + */
> > +
> 
> ..snip..
> 
fixed in patch:v5.
> > +
> > +static const struct gc08a3_link_freq_config
> > gc08a3_link_freq_336m_configs = {
> > +	.reg_list = {
> > +		.num_of_regs = ARRAY_SIZE(mode_table_common),
> > +		.regs = mode_table_common,
> > +	}
> > +};
> > +
> > +static const struct gc08a3_link_freq_config
> > gc08a3_link_freq_207m_configs = {
> > +	.reg_list = {
> > +		.num_of_regs = ARRAY_SIZE(mode_table_common),
> > +		.regs = mode_table_common,
> > +	}
> > +};
> > +
> 
> Since you're documenting this structure anyway, why not kerneldoc? :-
> )
> 
As these registers are the same, I followed Mr.Laurent's comments and
droped this "gc08a3_link_freq_config" structure.

> > +struct gc08a3_mode {
> > +	u32 width;
> > +	u32 height;
> > +	const struct gc08a3_reg_list reg_list;
> > +
> > +	u32 hts; /* Horizontal timining size */
> > +	u32 vts_def; /* Default vertical timining size */
> > +	u32 vts_min; /* Min vertical timining size */
> > +	u32 max_framerate;
> > +	const struct gc08a3_link_freq_config *link_freq_configs;
> > +};
> > +
> > +/*
> > + * Declare modes in order, from biggest
> > + * to smallest height.
> > + */
> 
> one line is enough for this comment.
> 
fixed in patch:v5.
> > +static const struct gc08a3_mode gc08a3_modes[] = {
> > +	{
> > +		.width = GC08A3_NATIVE_WIDTH,
> > +		.height = GC08A3_NATIVE_HEIGHT,
> > +		.reg_list = {
> > +			.num_of_regs = ARRAY_SIZE(mode_3264x2448),
> > +			.regs = mode_3264x2448,
> > +		},
> > +		.link_freq_configs = &gc08a3_link_freq_336m_configs,
> > +
> > +		.hts = GC08A3_HTS_30FPS,
> > +		.vts_def = GC08A3_VTS_30FPS,
> > +		.vts_min = GC08A3_VTS_30FPS_MIN,
> > +		.max_framerate = 300,
> > +	},
> > +	{
> > +		.width = 1920,
> > +		.height = 1080,
> > +		.reg_list = {
> > +			.num_of_regs = ARRAY_SIZE(mode_1920x1080),
> > +			.regs = mode_1920x1080,
> > +		},
> > +		.link_freq_configs = &gc08a3_link_freq_207m_configs,
> > +
> > +		.hts = GC08A3_HTS_60FPS,
> > +		.vts_def = GC08A3_VTS_60FPS,
> > +		.vts_min = GC08A3_VTS_60FPS_MIN,
> > +		.max_framerate = 600,
> > +	},
> > +};
> > +
> > +static u64 to_pixel_rate(u32 f_index)
> > +{
> > +	u64 pixel_rate = link_freq_menu_items[f_index] * 2 *
> > GC08A3_DATA_LANES;
> > +
> > +	do_div(pixel_rate, GC08A3_RGB_DEPTH);
> 
> The divisor is (less than) 32 bits and the dividend is always 64
> bits: that will
> break on builds for 32-bits CPUs.
> 
> Just do....
> 
> 	return div_u64(pixel_rate, GB08A3_RGB_DEPTH);
> 
fixed in patch:v5.
> > +
> > +	return pixel_rate;
> > +}
> > +
> > +static int gc08a3_identify_module(struct gc08a3 *gc08a3)
> > +{
> > +	struct i2c_client *client = v4l2_get_subdevdata(&gc08a3->sd);
> > +	u64 val = 0;
> 
> u64 val;
> 
> > +	int ret;
> > +
> 
> Either log here or in the probe function, otherwise it's just
> redudant.
> 
please review patch:v5.
> > +	ret = cci_read(gc08a3->regmap, GC08A3_REG_CHIP_ID, &val, NULL);
> > +	if (ret) {
> > +		dev_err(&client->dev,
> > +			"failed to read chip id: 0x%x",
> > GC08A3_CHIP_ID);
> > +		return ret;
> > +	}
> > +
> > +	if (val != GC08A3_CHIP_ID) {
> > +		dev_err(&client->dev, "chip id mismatch: 0x%x!=0x%llx",
> > +			GC08A3_CHIP_ID, val);
> > +		return -ENXIO;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static inline struct gc08a3 *to_gc08a3(struct v4l2_subdev *sd)
> > +{
> > +	return container_of(sd, struct gc08a3, sd);
> > +}
> > +
> 
> ..snip..
> 
fixed in patch:v5.
> > +
> > +static int gc08a3_update_cur_mode_controls(struct gc08a3 *gc08a3,
> > +					   const struct gc08a3_mode
> > *mode)
> > +{
> > +	s64 exposure_max, h_blank;
> > +	int ret = 0;
> > +
> > +	ret = __v4l2_ctrl_modify_range(gc08a3->vblank,
> > +				       mode->vts_min - mode->height,
> > +				       GC08A3_VTS_MAX - mode->height,
> > 1,
> > +				       mode->vts_def - mode->height);
> > +	if (ret)
> > +		dev_err(gc08a3->dev, "VB ctrl range update failed\n");
> > +
> > +	h_blank = mode->hts - mode->width;
> > +	ret = __v4l2_ctrl_modify_range(gc08a3->hblank, h_blank,
> > h_blank, 1,
> > +				       h_blank);
> > +	if (ret)
> > +		dev_err(gc08a3->dev, "HB ctrl range update failed\n");
> > +
> > +	exposure_max = mode->vts_def - GC08A3_EXP_MARGIN;
> > +	ret = __v4l2_ctrl_modify_range(gc08a3->exposure,
> > GC08A3_EXP_MIN,
> > +				       exposure_max, GC08A3_EXP_STEP,
> > +				       exposure_max);
> > +	if (ret)
> > +		dev_err(gc08a3->dev, "exposure ctrl range update
> > failed\n");
> 
> No. You're not returning anywhere for error. That's not okay.
> Besides...
> 
> 	if (ret) {
> 		dev_err..
> 		return ret;
> 	}
> 
> 	return 0;
> 
fixed in patch:v5.
> > +
> > +	return ret;
> > +}
> > +
> > +static void gc08a3_update_pad_format(struct gc08a3 *gc08a3,
> > +				     const struct gc08a3_mode *mode,
> > +				     struct v4l2_mbus_framefmt *fmt)
> > +{
> > +	fmt->width = mode->width;
> > +	fmt->height = mode->height;
> > +	fmt->code = GC08A3_MBUS_CODE;
> > +	fmt->field = V4L2_FIELD_NONE;
> > +	fmt->colorspace = V4L2_COLORSPACE_SRGB;
> > +	fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
> > +	fmt->quantization =
> > +		V4L2_MAP_QUANTIZATION_DEFAULT(true,
> > +					      fmt->colorspace,
> > +					      fmt->ycbcr_enc);
> > +	fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
> > +}
> > +
> > +static int gc08a3_set_format(struct v4l2_subdev *sd,
> > +			     struct v4l2_subdev_state *state,
> > +			     struct v4l2_subdev_format *fmt)
> > +{
> > +	struct gc08a3 *gc08a3 = to_gc08a3(sd);
> > +	struct v4l2_mbus_framefmt *mbus_fmt;
> > +	struct v4l2_rect *crop;
> > +	const struct gc08a3_mode *mode;
> > +
> > +	mode = v4l2_find_nearest_size(gc08a3_modes,
> > ARRAY_SIZE(gc08a3_modes),
> > +				      width, height, fmt->format.width,
> > +				      fmt->format.height);
> > +
> > +	/*update crop info to subdev state*/
> > +	crop = v4l2_subdev_state_get_crop(state, 0);
> > +	crop->width = mode->width;
> > +	crop->height = mode->height;
> > +
> > +	/*update fmt info to subdev state*/
> > +	gc08a3_update_pad_format(gc08a3, mode, &fmt->format);
> > +	mbus_fmt = v4l2_subdev_state_get_format(state, 0);
> > +	*mbus_fmt = fmt->format;
> > +
> > +	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
> > +		return 0;
> > +
> > +	gc08a3->cur_mode = mode;
> > +	gc08a3_update_cur_mode_controls(gc08a3, mode);
> > +
> > +	return 0;
> > +}
> > +
> > +static int gc08a3_get_selection(struct v4l2_subdev *sd,
> > +				struct v4l2_subdev_state *state,
> > +				struct v4l2_subdev_selection *sel)
> > +{
> > +	struct gc08a3 *gc08a3 = to_gc08a3(sd);
> > +
> > +	switch (sel->target) {
> > +	case V4L2_SEL_TGT_CROP:
> > +		sel->r = *v4l2_subdev_state_get_crop(state, 0);
> > +		break;
> > +	case V4L2_SEL_TGT_CROP_BOUNDS:
> > +		sel->r.top = 0;
> > +		sel->r.left = 0;
> > +		sel->r.width = GC08A3_NATIVE_WIDTH;
> > +		sel->r.height = GC08A3_NATIVE_HEIGHT;
> > +		break;
> > +	case V4L2_SEL_TGT_CROP_DEFAULT:
> > +		if (gc08a3->cur_mode->width == GC08A3_NATIVE_WIDTH) {
> > +			sel->r.top = 0;
> > +			sel->r.left = 0;
> > +			sel->r.width = gc08a3_modes[0].width;
> > +			sel->r.height = gc08a3_modes[0].height;
> > +		} else {
> > +			sel->r.top = 0;
> > +			sel->r.left = 0;
> > +			sel->r.width = gc08a3_modes[1].width;
> > +			sel->r.height = gc08a3_modes[1].height;
> > +		}
> > +		break;
> > +	default:
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int gc08a3_init_state(struct v4l2_subdev *sd,
> > +			     struct v4l2_subdev_state *state)
> > +{
> > +	struct v4l2_subdev_format fmt = {
> > +		.which = V4L2_SUBDEV_FORMAT_TRY,
> > +		.pad = 0,
> > +		.format = {
> > +			.code = GC08A3_MBUS_CODE,
> > +			.width = gc08a3_modes[0].width,
> > +			.height = gc08a3_modes[0].height,
> > +		},
> > +	};
> > +
> > +	gc08a3_set_format(sd, state, &fmt);
> > +
> > +	return 0;
> > +}
> > +
> > +static int gc08a3_set_ctrl_hflip(struct gc08a3 *gc08a3, u32
> > ctrl_val)
> > +{
> > +	int ret;
> > +	u64 val;
> > +
> > +	ret = cci_read(gc08a3->regmap, GC08A3_FLIP_REG, &val, NULL);
> > +	if (ret) {
> > +		dev_err(gc08a3->dev, "read hflip register failed:
> > %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	val = ctrl_val ? (val | GC08A3_FLIP_H_MASK) :
> > +			   (val & ~GC08A3_FLIP_H_MASK);
> > +	ret = cci_write(gc08a3->regmap, GC08A3_FLIP_REG, val, NULL);
> > +	if (ret < 0)
> > +		dev_err(gc08a3->dev, "Error %d\n", ret);
> > +
> > +	return ret;
> > +}
> > +
> > +static int gc08a3_set_ctrl_vflip(struct gc08a3 *gc08a3, u32
> > ctrl_val)
> > +{
> > +	int ret;
> > +	u64 val;
> > +
> > +	ret = cci_read(gc08a3->regmap, GC08A3_FLIP_REG, &val, NULL);
> > +	if (ret) {
> > +		dev_err(gc08a3->dev, "read vflip register failed:
> > %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	val = ctrl_val ? (val | GC08A3_FLIP_V_MASK) :
> > +			   (val & ~GC08A3_FLIP_V_MASK);
> > +	ret = cci_write(gc08a3->regmap, GC08A3_FLIP_REG, val, NULL);
> > +	if (ret < 0)
> > +		dev_err(gc08a3->dev, "Error %d\n", ret);
> > +
> > +	return ret;
> > +}
> > +
> > +static int gc08a3_test_pattern(struct gc08a3 *gc08a3, u32
> > pattern_menu)
> > +{
> > +	u32 pattern = 0;
> > +	int ret;
> 
> ret not initialized is ok here;
> 
> > +
> > +	if (pattern_menu) {
> > +		switch (pattern_menu) {
> > +		case 1:
> > +			pattern = 0x00;
> > +			break;
> > +		case 2:
> > +			pattern = 0x10;
> > +			break;
> > +		case 3:
> > +		case 4:
> > +		case 5:
> > +		case 6:
> > +		case 7:
> > +			pattern = pattern_menu + 1;
> > +			break;
> > +		}
> > +
> > +		ret = cci_write(gc08a3->regmap,
> > GC08A3_REG_TEST_PATTERN_EN,
> > +				GC08A3_TEST_PATTERN_EN, NULL);
> > +		if (ret)
> > +			return ret;
> > +
> > +		ret = cci_write(gc08a3->regmap,
> > GC08A3_REG_TEST_PATTERN_IDX,
> > +				pattern, NULL);
> 
> if (ret)
> 	return ret;
> 
> > +
> > +	} else {
> > +		ret = cci_write(gc08a3->regmap,
> > GC08A3_REG_TEST_PATTERN_EN,
> > +				0x00, NULL);
> 
> if (ret)
> 	return ret;
> 
> > +	}
> > +
> 
> 	return 0;
> 
fixed in patch:v5.

> > +	return ret;
> > +}
> > +
> > +static int gc08a3_set_ctrl(struct v4l2_ctrl *ctrl)
> > +{
> > +	struct gc08a3 *gc08a3 =
> > +		container_of(ctrl->handler, struct gc08a3, ctrls);
> > +	int ret = 0;
> 
> int ret;
> 
> > +	s64 exposure_max;
> > +
> > +	if (ctrl->id == V4L2_CID_VBLANK) {
> > +		/* Update max exposure while meeting expected vblanking
> > */
> > +		exposure_max = gc08a3->cur_mode->height + ctrl->val -
> > +			       GC08A3_EXP_MARGIN;
> > +		__v4l2_ctrl_modify_range(gc08a3->exposure,
> > +					 gc08a3->exposure->minimum,
> > +					 exposure_max, gc08a3-
> > >exposure->step,
> > +					 exposure_max);
> > +	}
> > +
> > +	/*
> > +	 * Applying V4L2 control value only happens
> > +	 * when power is on for streaming
> > +	 */
> > +	if (!pm_runtime_get_if_in_use(gc08a3->dev))
> > +		return 0;
> > +
> > +	switch (ctrl->id) {
> > +	case V4L2_CID_EXPOSURE:
> > +		ret = cci_write(gc08a3->regmap, GC08A3_EXP_REG,
> > +				ctrl->val, NULL);
> > +		break;
> > +
> > +	case V4L2_CID_ANALOGUE_GAIN:
> > +		ret = cci_write(gc08a3->regmap, GC08A3_AGAIN_REG,
> > +				ctrl->val, NULL);
> > +		break;
> > +
> > +	case V4L2_CID_VBLANK:
> > +		ret = cci_write(gc08a3->regmap,
> > GC08A3_FRAME_LENGTH_REG,
> > +				gc08a3->cur_mode->height + ctrl->val,
> > NULL);
> > +		break;
> > +
> > +	case V4L2_CID_HFLIP:
> > +		ret = gc08a3_set_ctrl_hflip(gc08a3, ctrl->val);
> > +		break;
> > +
> > +	case V4L2_CID_VFLIP:
> > +		ret = gc08a3_set_ctrl_vflip(gc08a3, ctrl->val);
> > +		break;
> > +
> > +	case V4L2_CID_TEST_PATTERN:
> > +		ret = gc08a3_test_pattern(gc08a3, ctrl->val);
> > +		break;
> > +
> > +	default:
> > +		break;
> > +	}
> > +
> > +	pm_runtime_put(gc08a3->dev);
> 
> if (ret)
> 	return ret;
> 
> return 0;
> 
As "default" case is not assign the variable "ret", this return value
is not expected, so we need initialize the variable "ret=0". Can we
keep this coding style?
> > +
> > +	return ret;
> > +}
> > +
> 
> ...and I've ignored some more stuff as other reviewers already gave
> you feedback.
> 
> Regards,
> Angelo
> 

      reply	other threads:[~2024-02-20  2:21 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-04  6:15 [PATCH v4 0/2] media: i2c: Add support for GC08A3 sensor Zhi Mao
2024-02-04  6:15 ` [PATCH v4 1/2] media: dt-bindings: i2c: add GalaxyCore GC08A3 image sensor Zhi Mao
2024-02-04 13:50   ` Laurent Pinchart
2024-02-07 14:42   ` AngeloGioacchino Del Regno
2024-02-04  6:15 ` [PATCH v4 2/2] media: i2c: Add GC08A3 image sensor driver Zhi Mao
2024-02-06 18:45   ` Laurent Pinchart
2024-02-20  2:12     ` Zhi Mao (毛智)
2024-02-20  3:01       ` Laurent Pinchart
2024-02-20  5:45         ` Zhi Mao (毛智)
2024-02-20  7:25           ` sakari.ailus
2024-02-21  2:37             ` Zhi Mao (毛智)
2024-02-21  7:43               ` sakari.ailus
2024-02-27  1:36                 ` Zhi Mao (毛智)
2024-02-07 14:42   ` AngeloGioacchino Del Regno
2024-02-20  2:21     ` Zhi Mao (毛智) [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1a9cb6c04de90cde777e30e15b0bced4c1d002f9.camel@mediatek.com \
    --to=zhi.mao@mediatek.com \
    --cc=10572168@qq.com \
    --cc=Project_Global_Chrome_Upstream_Group@mediatek.com \
    --cc=Yaya.Chang@mediatek.com \
    --cc=andy.shevchenko@gmail.com \
    --cc=angelogioacchino.delregno@collabora.com \
    --cc=bingbu.cao@intel.com \
    --cc=conor+dt@kernel.org \
    --cc=dan.scally@ideasonboard.com \
    --cc=devicetree@vger.kernel.org \
    --cc=gerald.loacker@wolfvision.net \
    --cc=hdegoede@redhat.com \
    --cc=heiko@sntech.de \
    --cc=hverkuil-cisco@xs4all.nl \
    --cc=jacopo.mondi@ideasonboard.com \
    --cc=jernej.skrabec@gmail.com \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=macromorgan@hotmail.com \
    --cc=matthias.bgg@gmail.com \
    --cc=mchehab@kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=sakari.ailus@linux.intel.com \
    --cc=shengnan.wang@mediatek.com \
    --cc=tomi.valkeinen@ideasonboard.com \
    --cc=yunkec@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).