mbox series

[v8,00/22] Add support for the SDM845 Camera Subsystem

Message ID 20210315155942.640889-1-robert.foss@linaro.org
Headers show
Series Add support for the SDM845 Camera Subsystem | expand

Message

Robert Foss March 15, 2021, 3:59 p.m. UTC
This series implements support for the camera subsystem found in
the SDM845 SOCs and the Titan 170 ISP. The support is partial
in that it implements CSIPHY, CSID, and partial VFE support.

The Titan generation of the ISP diverges a fair amount from the
design of the previous architecture generation, CAMSS. As a result
some pretty invasive refactoring is done in this series. It also
means that at this time we're unable to implement support for all
of the IP blocks contained. This is due to a combination of legal
considerations with respect to the IP and its owner Qualcomm and
time & man hour constrains on the Linaro side.

The CSIPHY (CSI Physical Layer) & CSID (CSI Decoder) support is
complete, but the VFE (Video Front End, which is referred to as IFE
(Image Front End) in the Titan generation of ISPs) only has support
for the RDI (Raw Dump Interface) which allows the raw output of
the CSID to be written to memory.

The 2nd interface implemented in the VFE silicon is the PIX
interface, and camss does not support it for this generation of ISPs.
The reason for this is that the PIX interface is used for sending
image data to the BPS (Bayer Processing Section) & IPE (Image
Processing Engine), but both of these units are beyond the scope
of enabling basic ISP functionality for the SDM845.

Since the Titan architecture generation diverges quite a bit from
the CAMSS generation, a lot of pretty major refactoring is carried
out in this series. Both the CSID & VFE core paths are made more
general and hardware version specific parts are broken out.
The CSIPHY didn't require quite as radical changes and therefore
keeps its current form.

Tested on:
 - Qcom RB3 / db845c + camera mezzanine, which is SDM845 based
 - db410c + D3 Camera mezzanine, which is APQ8016 based
 
Branch:
 - https://git.linaro.org/people/robert.foss/linux.git/log/?h=camss_sdm845_v1
 - https://git.linaro.org/people/robert.foss/linux.git/log/?h=camss_sdm845_v2
 - https://git.linaro.org/people/robert.foss/linux.git/log/?h=camss_sdm845_v3
 - https://git.linaro.org/people/robert.foss/linux.git/log/?h=camss_sdm845_v4
 - https://git.linaro.org/people/robert.foss/linux.git/log/?h=camss_sdm845_v5
 - https://git.linaro.org/people/robert.foss/linux.git/log/?h=camss_sdm845_v6
 - https://git.linaro.org/people/robert.foss/linux.git/log/?h=camss_sdm845_v7
 - https://git.linaro.org/people/robert.foss/linux.git/log/?h=camss_sdm845_v8



Robert Foss (22):
  media: camss: Fix vfe_isr_comp_done() documentation
  media: camss: Fix vfe_isr comment typo
  media: camss: Replace trace_printk() with dev_dbg()
  media: camss: Add CAMSS_845 camss version
  media: camss: Make ISPIF subdevice optional
  media: camss: Refactor VFE HW version support
  media: camss: Add support for VFE hardware version Titan 170
  media: camss: Add missing format identifiers
  media: camss: Refactor CSID HW version support
  media: camss: Add support for CSID hardware version Titan 170
  media: camss: Add support for CSIPHY hardware version Titan 170
  media: camss: Refactor VFE power domain toggling
  media: camss: Enable SDM845
  dt-bindings: media: camss: Add qcom,msm8916-camss binding
  dt-bindings: media: camss: Add qcom,msm8996-camss binding
  dt-bindings: media: camss: Add qcom,sdm660-camss binding
  dt-bindings: media: camss: Add qcom,sdm845-camss binding
  MAINTAINERS: Change CAMSS documentation to use dtschema bindings
  media: dt-bindings: media: Remove qcom,camss documentation
  arm64: dts: sdm845: Add CAMSS ISP node
  arm64: dts: sdm845-db845c: Configure regulators for camss node
  arm64: dts: sdm845-db845c: Enable ov8856 sensor and connect to ISP

 .../devicetree/bindings/media/qcom,camss.txt  |  236 ----
 .../bindings/media/qcom,msm8916-camss.yaml    |  256 ++++
 .../bindings/media/qcom,msm8996-camss.yaml    |  387 ++++++
 .../bindings/media/qcom,sdm660-camss.yaml     |  398 ++++++
 .../bindings/media/qcom,sdm845-camss.yaml     |  371 +++++
 MAINTAINERS                                   |    2 +-
 arch/arm64/boot/dts/qcom/sdm845-db845c.dts    |   23 +-
 arch/arm64/boot/dts/qcom/sdm845.dtsi          |  135 ++
 drivers/media/platform/qcom/camss/Makefile    |    6 +
 .../platform/qcom/camss/camss-csid-170.c      |  599 +++++++++
 .../platform/qcom/camss/camss-csid-4-1.c      |  328 +++++
 .../platform/qcom/camss/camss-csid-4-7.c      |  404 ++++++
 .../platform/qcom/camss/camss-csid-gen1.h     |   27 +
 .../platform/qcom/camss/camss-csid-gen2.h     |   39 +
 .../media/platform/qcom/camss/camss-csid.c    |  627 +--------
 .../media/platform/qcom/camss/camss-csid.h    |  161 ++-
 .../qcom/camss/camss-csiphy-3ph-1-0.c         |  179 ++-
 .../media/platform/qcom/camss/camss-csiphy.c  |   66 +-
 .../media/platform/qcom/camss/camss-ispif.c   |  119 +-
 .../media/platform/qcom/camss/camss-ispif.h   |    3 +-
 .../media/platform/qcom/camss/camss-vfe-170.c |  786 +++++++++++
 .../media/platform/qcom/camss/camss-vfe-4-1.c |  144 +-
 .../media/platform/qcom/camss/camss-vfe-4-7.c |  277 ++--
 .../media/platform/qcom/camss/camss-vfe-4-8.c | 1195 +++++++++++++++++
 .../platform/qcom/camss/camss-vfe-gen1.c      |  742 ++++++++++
 .../platform/qcom/camss/camss-vfe-gen1.h      |  117 ++
 drivers/media/platform/qcom/camss/camss-vfe.c |  847 +-----------
 drivers/media/platform/qcom/camss/camss-vfe.h |  128 +-
 .../media/platform/qcom/camss/camss-video.c   |   52 +
 drivers/media/platform/qcom/camss/camss.c     |  410 +++++-
 drivers/media/platform/qcom/camss/camss.h     |   15 +-
 31 files changed, 7027 insertions(+), 2052 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/media/qcom,camss.txt
 create mode 100644 Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml
 create mode 100644 Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml
 create mode 100644 Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml
 create mode 100644 Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml
 create mode 100644 drivers/media/platform/qcom/camss/camss-csid-170.c
 create mode 100644 drivers/media/platform/qcom/camss/camss-csid-4-1.c
 create mode 100644 drivers/media/platform/qcom/camss/camss-csid-4-7.c
 create mode 100644 drivers/media/platform/qcom/camss/camss-csid-gen1.h
 create mode 100644 drivers/media/platform/qcom/camss/camss-csid-gen2.h
 create mode 100644 drivers/media/platform/qcom/camss/camss-vfe-170.c
 create mode 100644 drivers/media/platform/qcom/camss/camss-vfe-4-8.c
 create mode 100644 drivers/media/platform/qcom/camss/camss-vfe-gen1.c
 create mode 100644 drivers/media/platform/qcom/camss/camss-vfe-gen1.h

Comments

Hans Verkuil March 16, 2021, 9:40 a.m. UTC | #1
On 15/03/2021 16:59, Robert Foss wrote:
> In order to support Qualcomm ISP hardware architectures that diverge

> from older architectures, the VFE subdevice driver needs to be refactored

> to better abstract the different ISP architectures.

> 

> Gen1 represents the CAMSS ISP architecture. The ISP architecture developed

> after CAMSS, Titan, will be referred to as Gen2.

> 

> Signed-off-by: Robert Foss <robert.foss@linaro.org>

> Reviewed-by: Andrey Konovalov <andrey.konovalov@linaro.org>

> ---

> 

> 


<snip>

> diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h

> index 5bce6736e4bb..ceff4985b1cc 100644

> --- a/drivers/media/platform/qcom/camss/camss-vfe.h

> +++ b/drivers/media/platform/qcom/camss/camss-vfe.h

> @@ -17,15 +17,26 @@

>  #include <media/v4l2-subdev.h>

>  

>  #include "camss-video.h"

> +#include "camss-vfe-gen1.h"

>  

>  #define MSM_VFE_PAD_SINK 0

>  #define MSM_VFE_PAD_SRC 1

>  #define MSM_VFE_PADS_NUM 2

>  

> -#define MSM_VFE_LINE_NUM 4

>  #define MSM_VFE_IMAGE_MASTERS_NUM 7

>  #define MSM_VFE_COMPOSITE_IRQ_NUM 4

>  

> +/* VFE halt timeout */

> +#define VFE_HALT_TIMEOUT_MS 100

> +/* Frame drop value. VAL + UPDATES - 1 should not exceed 31 */

> +#define VFE_FRAME_DROP_VAL 30

> +

> +#define vfe_line_array(ptr_line)	\

> +	((const struct vfe_line (*)[]) &(ptr_line[-(ptr_line->id)]))


I get a checkpatch warning on this:

CHECK: Unnecessary parentheses around ptr_line[-(ptr_line->id)]
#3612: FILE: drivers/media/platform/qcom/camss/camss-vfe.h:35:
+       ((const struct vfe_line (*)[]) &(ptr_line[-(ptr_line->id)]))

This should be:

	((const struct vfe_line (*)[]) &(ptr_line)[-(ptr_line)->id])

The checkpatch message is a bit odd, the real problem here is the missing
parenthesis around ptr_line: this would cause problems if ptr_line is an
expression like 'ptr + 5', which would lead to a bad expansion.

Regards,

	Hans

> +

> +#define to_vfe(ptr_line)	\

> +	container_of(vfe_line_array(ptr_line), struct vfe_device, line)

> +

>  enum vfe_output_state {

>  	VFE_OUTPUT_OFF,

>  	VFE_OUTPUT_RESERVED,

> @@ -40,23 +51,30 @@ enum vfe_line_id {

>  	VFE_LINE_RDI0 = 0,

>  	VFE_LINE_RDI1 = 1,

>  	VFE_LINE_RDI2 = 2,

> -	VFE_LINE_PIX = 3

> +	VFE_LINE_PIX = 3,

> +	VFE_LINE_NUM_GEN1 = 4,

> +	VFE_LINE_NUM_MAX = 4

>  };

>  

>  struct vfe_output {

>  	u8 wm_num;

>  	u8 wm_idx[3];

>  

> -	int active_buf;

>  	struct camss_buffer *buf[2];

>  	struct camss_buffer *last_buffer;

>  	struct list_head pending_bufs;

>  

>  	unsigned int drop_update_idx;

>  

> +	union {

> +		struct {

> +			int active_buf;

> +			int wait_sof;

> +		} gen1;

> +	};

>  	enum vfe_output_state state;

>  	unsigned int sequence;

> -	int wait_sof;

> +

>  	int wait_reg_update;

>  	struct completion sof;

>  	struct completion reg_update;

> @@ -78,59 +96,19 @@ struct vfe_line {

>  struct vfe_device;

>  

>  struct vfe_hw_ops {

> -	void (*hw_version_read)(struct vfe_device *vfe, struct device *dev);

> -	u16 (*get_ub_size)(u8 vfe_id);

> +	void (*enable_irq_common)(struct vfe_device *vfe);

>  	void (*global_reset)(struct vfe_device *vfe);

> -	void (*halt_request)(struct vfe_device *vfe);

> -	void (*halt_clear)(struct vfe_device *vfe);

> -	void (*wm_enable)(struct vfe_device *vfe, u8 wm, u8 enable);

> -	void (*wm_frame_based)(struct vfe_device *vfe, u8 wm, u8 enable);

> -	void (*wm_line_based)(struct vfe_device *vfe, u32 wm,

> -			      struct v4l2_pix_format_mplane *pix,

> -			      u8 plane, u32 enable);

> -	void (*wm_set_framedrop_period)(struct vfe_device *vfe, u8 wm, u8 per);

> -	void (*wm_set_framedrop_pattern)(struct vfe_device *vfe, u8 wm,

> -					 u32 pattern);

> -	void (*wm_set_ub_cfg)(struct vfe_device *vfe, u8 wm, u16 offset,

> -			      u16 depth);

> -	void (*bus_reload_wm)(struct vfe_device *vfe, u8 wm);

> -	void (*wm_set_ping_addr)(struct vfe_device *vfe, u8 wm, u32 addr);

> -	void (*wm_set_pong_addr)(struct vfe_device *vfe, u8 wm, u32 addr);

> -	int (*wm_get_ping_pong_status)(struct vfe_device *vfe, u8 wm);

> -	void (*bus_enable_wr_if)(struct vfe_device *vfe, u8 enable);

> -	void (*bus_connect_wm_to_rdi)(struct vfe_device *vfe, u8 wm,

> -				      enum vfe_line_id id);

> -	void (*wm_set_subsample)(struct vfe_device *vfe, u8 wm);

> -	void (*bus_disconnect_wm_from_rdi)(struct vfe_device *vfe, u8 wm,

> -					   enum vfe_line_id id);

> -	void (*set_xbar_cfg)(struct vfe_device *vfe, struct vfe_output *output,

> -			     u8 enable);

> -	void (*set_rdi_cid)(struct vfe_device *vfe, enum vfe_line_id id,

> -			    u8 cid);

> -	void (*set_realign_cfg)(struct vfe_device *vfe, struct vfe_line *line,

> -				u8 enable);

> +	void (*hw_version_read)(struct vfe_device *vfe, struct device *dev);

> +	irqreturn_t (*isr)(int irq, void *dev);

> +	void (*isr_read)(struct vfe_device *vfe, u32 *value0, u32 *value1);

>  	void (*reg_update)(struct vfe_device *vfe, enum vfe_line_id line_id);

>  	void (*reg_update_clear)(struct vfe_device *vfe,

>  				 enum vfe_line_id line_id);

> -	void (*enable_irq_wm_line)(struct vfe_device *vfe, u8 wm,

> -				   enum vfe_line_id line_id, u8 enable);

> -	void (*enable_irq_pix_line)(struct vfe_device *vfe, u8 comp,

> -				    enum vfe_line_id line_id, u8 enable);

> -	void (*enable_irq_common)(struct vfe_device *vfe);

> -	void (*set_demux_cfg)(struct vfe_device *vfe, struct vfe_line *line);

> -	void (*set_scale_cfg)(struct vfe_device *vfe, struct vfe_line *line);

> -	void (*set_crop_cfg)(struct vfe_device *vfe, struct vfe_line *line);

> -	void (*set_clamp_cfg)(struct vfe_device *vfe);

> -	void (*set_qos)(struct vfe_device *vfe);

> -	void (*set_ds)(struct vfe_device *vfe);

> -	void (*set_cgc_override)(struct vfe_device *vfe, u8 wm, u8 enable);

> -	void (*set_camif_cfg)(struct vfe_device *vfe, struct vfe_line *line);

> -	void (*set_camif_cmd)(struct vfe_device *vfe, u8 enable);

> -	void (*set_module_cfg)(struct vfe_device *vfe, u8 enable);

> -	int (*camif_wait_for_stop)(struct vfe_device *vfe, struct device *dev);

> -	void (*isr_read)(struct vfe_device *vfe, u32 *value0, u32 *value1);

> +	void (*subdev_init)(struct device *dev, struct vfe_device *vfe);

> +	int (*vfe_disable)(struct vfe_line *line);

> +	int (*vfe_enable)(struct vfe_line *line);

> +	int (*vfe_halt)(struct vfe_device *vfe);

>  	void (*violation_read)(struct vfe_device *vfe);

> -	irqreturn_t (*isr)(int irq, void *dev);

>  };

>  

>  struct vfe_isr_ops {

> @@ -158,11 +136,14 @@ struct vfe_device {

>  	int stream_count;

>  	spinlock_t output_lock;

>  	enum vfe_line_id wm_output_map[MSM_VFE_IMAGE_MASTERS_NUM];

> -	struct vfe_line line[MSM_VFE_LINE_NUM];

> +	struct vfe_line line[VFE_LINE_NUM_MAX];

> +	u8 line_num;

>  	u32 reg_update;

>  	u8 was_streaming;

>  	const struct vfe_hw_ops *ops;

> +	const struct vfe_hw_ops_gen1 *ops_gen1;

>  	struct vfe_isr_ops isr_ops;

> +	struct camss_video_ops video_ops;

>  };

>  

>  struct resources;

> @@ -178,6 +159,37 @@ void msm_vfe_unregister_entities(struct vfe_device *vfe);

>  void msm_vfe_get_vfe_id(struct media_entity *entity, u8 *id);

>  void msm_vfe_get_vfe_line_id(struct media_entity *entity, enum vfe_line_id *id);

>  

> +/*

> + * vfe_buf_add_pending - Add output buffer to list of pending

> + * @output: VFE output

> + * @buffer: Video buffer

> + */

> +void vfe_buf_add_pending(struct vfe_output *output, struct camss_buffer *buffer);

> +

> +struct camss_buffer *vfe_buf_get_pending(struct vfe_output *output);

> +

> +/*

> + * vfe_disable - Disable streaming on VFE line

> + * @line: VFE line

> + *

> + * Return 0 on success or a negative error code otherwise

> + */

> +int vfe_disable(struct vfe_line *line);

> +

> +int vfe_flush_buffers(struct camss_video *vid, enum vb2_buffer_state state);

> +

> +/*

> + * vfe_isr_comp_done - Process composite image done interrupt

> + * @vfe: VFE Device

> + * @comp: Composite image id

> + */

> +void vfe_isr_comp_done(struct vfe_device *vfe, u8 comp);

> +

> +void vfe_isr_reset_ack(struct vfe_device *vfe);

> +int vfe_put_output(struct vfe_line *line);

> +int vfe_release_wm(struct vfe_device *vfe, u8 wm);

> +int vfe_reserve_wm(struct vfe_device *vfe, enum vfe_line_id line_id);

> +

>  extern const struct vfe_hw_ops vfe_ops_4_1;

>  extern const struct vfe_hw_ops vfe_ops_4_7;

>  extern const struct vfe_hw_ops vfe_ops_4_8;

> diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c

> index 0c679c97da6d..49e25c837bdc 100644

> --- a/drivers/media/platform/qcom/camss/camss.c

> +++ b/drivers/media/platform/qcom/camss/camss.c

> @@ -881,7 +881,7 @@ static int camss_register_entities(struct camss *camss)

>  

>  		for (i = 0; i < camss->ispif->line_num; i++)

>  			for (k = 0; k < camss->vfe_num; k++)

> -				for (j = 0; j < ARRAY_SIZE(camss->vfe[k].line); j++) {

> +				for (j = 0; j < camss->vfe[k].line_num; j++) {

>  					struct v4l2_subdev *ispif = &camss->ispif->line[i].subdev;

>  					struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev;

>  

> @@ -902,7 +902,7 @@ static int camss_register_entities(struct camss *camss)

>  	} else {

>  		for (i = 0; i < camss->csid_num; i++)

>  			for (k = 0; k < camss->vfe_num; k++)

> -				for (j = 0; j < ARRAY_SIZE(camss->vfe[k].line); j++) {

> +				for (j = 0; j < camss->vfe[k].line_num; j++) {

>  					struct v4l2_subdev *csid = &camss->csid[i].subdev;

>  					struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev;

>  

>
Robert Foss March 16, 2021, 11:02 a.m. UTC | #2
Hey Hans,

Thanks for having a look!

On Tue, 16 Mar 2021 at 10:41, Hans Verkuil <hverkuil@xs4all.nl> wrote:
>
> On 15/03/2021 16:59, Robert Foss wrote:
> > In order to support Qualcomm ISP hardware architectures that diverge
> > from older architectures, the VFE subdevice driver needs to be refactored
> > to better abstract the different ISP architectures.
> >
> > Gen1 represents the CAMSS ISP architecture. The ISP architecture developed
> > after CAMSS, Titan, will be referred to as Gen2.
> >
> > Signed-off-by: Robert Foss <robert.foss@linaro.org>
> > Reviewed-by: Andrey Konovalov <andrey.konovalov@linaro.org>
> > ---
> >
> >
>
> <snip>
>
> > diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h
> > index 5bce6736e4bb..ceff4985b1cc 100644
> > --- a/drivers/media/platform/qcom/camss/camss-vfe.h
> > +++ b/drivers/media/platform/qcom/camss/camss-vfe.h
> > @@ -17,15 +17,26 @@
> >  #include <media/v4l2-subdev.h>
> >
> >  #include "camss-video.h"
> > +#include "camss-vfe-gen1.h"
> >
> >  #define MSM_VFE_PAD_SINK 0
> >  #define MSM_VFE_PAD_SRC 1
> >  #define MSM_VFE_PADS_NUM 2
> >
> > -#define MSM_VFE_LINE_NUM 4
> >  #define MSM_VFE_IMAGE_MASTERS_NUM 7
> >  #define MSM_VFE_COMPOSITE_IRQ_NUM 4
> >
> > +/* VFE halt timeout */
> > +#define VFE_HALT_TIMEOUT_MS 100
> > +/* Frame drop value. VAL + UPDATES - 1 should not exceed 31 */
> > +#define VFE_FRAME_DROP_VAL 30
> > +
> > +#define vfe_line_array(ptr_line)     \
> > +     ((const struct vfe_line (*)[]) &(ptr_line[-(ptr_line->id)]))
>
> I get a checkpatch warning on this:
>
> CHECK: Unnecessary parentheses around ptr_line[-(ptr_line->id)]
> #3612: FILE: drivers/media/platform/qcom/camss/camss-vfe.h:35:
> +       ((const struct vfe_line (*)[]) &(ptr_line[-(ptr_line->id)]))
>
> This should be:
>
>         ((const struct vfe_line (*)[]) &(ptr_line)[-(ptr_line)->id])
>
> The checkpatch message is a bit odd, the real problem here is the missing
> parenthesis around ptr_line: this would cause problems if ptr_line is an
> expression like 'ptr + 5', which would lead to a bad expansion.
>

Ack

> Regards,
>
>         Hans
>
> > +
> > +#define to_vfe(ptr_line)     \
> > +     container_of(vfe_line_array(ptr_line), struct vfe_device, line)
> > +
> >  enum vfe_output_state {
> >       VFE_OUTPUT_OFF,
> >       VFE_OUTPUT_RESERVED,
> > @@ -40,23 +51,30 @@ enum vfe_line_id {
> >       VFE_LINE_RDI0 = 0,
> >       VFE_LINE_RDI1 = 1,
> >       VFE_LINE_RDI2 = 2,
> > -     VFE_LINE_PIX = 3
> > +     VFE_LINE_PIX = 3,
> > +     VFE_LINE_NUM_GEN1 = 4,
> > +     VFE_LINE_NUM_MAX = 4
> >  };
> >
> >  struct vfe_output {
> >       u8 wm_num;
> >       u8 wm_idx[3];
> >
> > -     int active_buf;
> >       struct camss_buffer *buf[2];
> >       struct camss_buffer *last_buffer;
> >       struct list_head pending_bufs;
> >
> >       unsigned int drop_update_idx;
> >
> > +     union {
> > +             struct {
> > +                     int active_buf;
> > +                     int wait_sof;
> > +             } gen1;
> > +     };
> >       enum vfe_output_state state;
> >       unsigned int sequence;
> > -     int wait_sof;
> > +
> >       int wait_reg_update;
> >       struct completion sof;
> >       struct completion reg_update;
> > @@ -78,59 +96,19 @@ struct vfe_line {
> >  struct vfe_device;
> >
> >  struct vfe_hw_ops {
> > -     void (*hw_version_read)(struct vfe_device *vfe, struct device *dev);
> > -     u16 (*get_ub_size)(u8 vfe_id);
> > +     void (*enable_irq_common)(struct vfe_device *vfe);
> >       void (*global_reset)(struct vfe_device *vfe);
> > -     void (*halt_request)(struct vfe_device *vfe);
> > -     void (*halt_clear)(struct vfe_device *vfe);
> > -     void (*wm_enable)(struct vfe_device *vfe, u8 wm, u8 enable);
> > -     void (*wm_frame_based)(struct vfe_device *vfe, u8 wm, u8 enable);
> > -     void (*wm_line_based)(struct vfe_device *vfe, u32 wm,
> > -                           struct v4l2_pix_format_mplane *pix,
> > -                           u8 plane, u32 enable);
> > -     void (*wm_set_framedrop_period)(struct vfe_device *vfe, u8 wm, u8 per);
> > -     void (*wm_set_framedrop_pattern)(struct vfe_device *vfe, u8 wm,
> > -                                      u32 pattern);
> > -     void (*wm_set_ub_cfg)(struct vfe_device *vfe, u8 wm, u16 offset,
> > -                           u16 depth);
> > -     void (*bus_reload_wm)(struct vfe_device *vfe, u8 wm);
> > -     void (*wm_set_ping_addr)(struct vfe_device *vfe, u8 wm, u32 addr);
> > -     void (*wm_set_pong_addr)(struct vfe_device *vfe, u8 wm, u32 addr);
> > -     int (*wm_get_ping_pong_status)(struct vfe_device *vfe, u8 wm);
> > -     void (*bus_enable_wr_if)(struct vfe_device *vfe, u8 enable);
> > -     void (*bus_connect_wm_to_rdi)(struct vfe_device *vfe, u8 wm,
> > -                                   enum vfe_line_id id);
> > -     void (*wm_set_subsample)(struct vfe_device *vfe, u8 wm);
> > -     void (*bus_disconnect_wm_from_rdi)(struct vfe_device *vfe, u8 wm,
> > -                                        enum vfe_line_id id);
> > -     void (*set_xbar_cfg)(struct vfe_device *vfe, struct vfe_output *output,
> > -                          u8 enable);
> > -     void (*set_rdi_cid)(struct vfe_device *vfe, enum vfe_line_id id,
> > -                         u8 cid);
> > -     void (*set_realign_cfg)(struct vfe_device *vfe, struct vfe_line *line,
> > -                             u8 enable);
> > +     void (*hw_version_read)(struct vfe_device *vfe, struct device *dev);
> > +     irqreturn_t (*isr)(int irq, void *dev);
> > +     void (*isr_read)(struct vfe_device *vfe, u32 *value0, u32 *value1);
> >       void (*reg_update)(struct vfe_device *vfe, enum vfe_line_id line_id);
> >       void (*reg_update_clear)(struct vfe_device *vfe,
> >                                enum vfe_line_id line_id);
> > -     void (*enable_irq_wm_line)(struct vfe_device *vfe, u8 wm,
> > -                                enum vfe_line_id line_id, u8 enable);
> > -     void (*enable_irq_pix_line)(struct vfe_device *vfe, u8 comp,
> > -                                 enum vfe_line_id line_id, u8 enable);
> > -     void (*enable_irq_common)(struct vfe_device *vfe);
> > -     void (*set_demux_cfg)(struct vfe_device *vfe, struct vfe_line *line);
> > -     void (*set_scale_cfg)(struct vfe_device *vfe, struct vfe_line *line);
> > -     void (*set_crop_cfg)(struct vfe_device *vfe, struct vfe_line *line);
> > -     void (*set_clamp_cfg)(struct vfe_device *vfe);
> > -     void (*set_qos)(struct vfe_device *vfe);
> > -     void (*set_ds)(struct vfe_device *vfe);
> > -     void (*set_cgc_override)(struct vfe_device *vfe, u8 wm, u8 enable);
> > -     void (*set_camif_cfg)(struct vfe_device *vfe, struct vfe_line *line);
> > -     void (*set_camif_cmd)(struct vfe_device *vfe, u8 enable);
> > -     void (*set_module_cfg)(struct vfe_device *vfe, u8 enable);
> > -     int (*camif_wait_for_stop)(struct vfe_device *vfe, struct device *dev);
> > -     void (*isr_read)(struct vfe_device *vfe, u32 *value0, u32 *value1);
> > +     void (*subdev_init)(struct device *dev, struct vfe_device *vfe);
> > +     int (*vfe_disable)(struct vfe_line *line);
> > +     int (*vfe_enable)(struct vfe_line *line);
> > +     int (*vfe_halt)(struct vfe_device *vfe);
> >       void (*violation_read)(struct vfe_device *vfe);
> > -     irqreturn_t (*isr)(int irq, void *dev);
> >  };
> >
> >  struct vfe_isr_ops {
> > @@ -158,11 +136,14 @@ struct vfe_device {
> >       int stream_count;
> >       spinlock_t output_lock;
> >       enum vfe_line_id wm_output_map[MSM_VFE_IMAGE_MASTERS_NUM];
> > -     struct vfe_line line[MSM_VFE_LINE_NUM];
> > +     struct vfe_line line[VFE_LINE_NUM_MAX];
> > +     u8 line_num;
> >       u32 reg_update;
> >       u8 was_streaming;
> >       const struct vfe_hw_ops *ops;
> > +     const struct vfe_hw_ops_gen1 *ops_gen1;
> >       struct vfe_isr_ops isr_ops;
> > +     struct camss_video_ops video_ops;
> >  };
> >
> >  struct resources;
> > @@ -178,6 +159,37 @@ void msm_vfe_unregister_entities(struct vfe_device *vfe);
> >  void msm_vfe_get_vfe_id(struct media_entity *entity, u8 *id);
> >  void msm_vfe_get_vfe_line_id(struct media_entity *entity, enum vfe_line_id *id);
> >
> > +/*
> > + * vfe_buf_add_pending - Add output buffer to list of pending
> > + * @output: VFE output
> > + * @buffer: Video buffer
> > + */
> > +void vfe_buf_add_pending(struct vfe_output *output, struct camss_buffer *buffer);
> > +
> > +struct camss_buffer *vfe_buf_get_pending(struct vfe_output *output);
> > +
> > +/*
> > + * vfe_disable - Disable streaming on VFE line
> > + * @line: VFE line
> > + *
> > + * Return 0 on success or a negative error code otherwise
> > + */
> > +int vfe_disable(struct vfe_line *line);
> > +
> > +int vfe_flush_buffers(struct camss_video *vid, enum vb2_buffer_state state);
> > +
> > +/*
> > + * vfe_isr_comp_done - Process composite image done interrupt
> > + * @vfe: VFE Device
> > + * @comp: Composite image id
> > + */
> > +void vfe_isr_comp_done(struct vfe_device *vfe, u8 comp);
> > +
> > +void vfe_isr_reset_ack(struct vfe_device *vfe);
> > +int vfe_put_output(struct vfe_line *line);
> > +int vfe_release_wm(struct vfe_device *vfe, u8 wm);
> > +int vfe_reserve_wm(struct vfe_device *vfe, enum vfe_line_id line_id);
> > +
> >  extern const struct vfe_hw_ops vfe_ops_4_1;
> >  extern const struct vfe_hw_ops vfe_ops_4_7;
> >  extern const struct vfe_hw_ops vfe_ops_4_8;
> > diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
> > index 0c679c97da6d..49e25c837bdc 100644
> > --- a/drivers/media/platform/qcom/camss/camss.c
> > +++ b/drivers/media/platform/qcom/camss/camss.c
> > @@ -881,7 +881,7 @@ static int camss_register_entities(struct camss *camss)
> >
> >               for (i = 0; i < camss->ispif->line_num; i++)
> >                       for (k = 0; k < camss->vfe_num; k++)
> > -                             for (j = 0; j < ARRAY_SIZE(camss->vfe[k].line); j++) {
> > +                             for (j = 0; j < camss->vfe[k].line_num; j++) {
> >                                       struct v4l2_subdev *ispif = &camss->ispif->line[i].subdev;
> >                                       struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev;
> >
> > @@ -902,7 +902,7 @@ static int camss_register_entities(struct camss *camss)
> >       } else {
> >               for (i = 0; i < camss->csid_num; i++)
> >                       for (k = 0; k < camss->vfe_num; k++)
> > -                             for (j = 0; j < ARRAY_SIZE(camss->vfe[k].line); j++) {
> > +                             for (j = 0; j < camss->vfe[k].line_num; j++) {
> >                                       struct v4l2_subdev *csid = &camss->csid[i].subdev;
> >                                       struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev;
> >
> >
>