summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/qcom/camss
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:03 +0000
commit01a69402cf9d38ff180345d55c2ee51c7e89fbc7 (patch)
treeb406c5242a088c4f59c6e4b719b783f43aca6ae9 /drivers/media/platform/qcom/camss
parentAdding upstream version 6.7.12. (diff)
downloadlinux-01a69402cf9d38ff180345d55c2ee51c7e89fbc7.tar.xz
linux-01a69402cf9d38ff180345d55c2ee51c7e89fbc7.zip
Adding upstream version 6.8.9.upstream/6.8.9
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/media/platform/qcom/camss')
-rw-r--r--drivers/media/platform/qcom/camss/camss-csid-gen2.c31
-rw-r--r--drivers/media/platform/qcom/camss/camss-csid.c20
-rw-r--r--drivers/media/platform/qcom/camss/camss-csid.h7
-rw-r--r--drivers/media/platform/qcom/camss/camss-csiphy.c15
-rw-r--r--drivers/media/platform/qcom/camss/camss-ispif.c17
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-170.c36
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-4-1.c8
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-4-7.c36
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-4-8.c31
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-480.c69
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe.c115
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe.h26
-rw-r--r--drivers/media/platform/qcom/camss/camss.c122
-rw-r--r--drivers/media/platform/qcom/camss/camss.h10
14 files changed, 277 insertions, 266 deletions
diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen2.c b/drivers/media/platform/qcom/camss/camss-csid-gen2.c
index 05ff5fa809..b11de4797c 100644
--- a/drivers/media/platform/qcom/camss/camss-csid-gen2.c
+++ b/drivers/media/platform/qcom/camss/camss-csid-gen2.c
@@ -21,7 +21,6 @@
* interface support. As a result of that it has an
* alternate register layout.
*/
-#define IS_LITE (csid->id >= 2 ? 1 : 0)
#define CSID_HW_VERSION 0x0
#define HW_VERSION_STEPPING 0
@@ -35,13 +34,13 @@
#define CSID_CSI2_RX_IRQ_MASK 0x24
#define CSID_CSI2_RX_IRQ_CLEAR 0x28
-#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) ((IS_LITE ? 0x30 : 0x40) \
+#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) ((csid_is_lite(csid) ? 0x30 : 0x40) \
+ 0x10 * (rdi))
-#define CSID_CSI2_RDIN_IRQ_MASK(rdi) ((IS_LITE ? 0x34 : 0x44) \
+#define CSID_CSI2_RDIN_IRQ_MASK(rdi) ((csid_is_lite(csid) ? 0x34 : 0x44) \
+ 0x10 * (rdi))
-#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) ((IS_LITE ? 0x38 : 0x48) \
+#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) ((csid_is_lite(csid) ? 0x38 : 0x48) \
+ 0x10 * (rdi))
-#define CSID_CSI2_RDIN_IRQ_SET(rdi) ((IS_LITE ? 0x3C : 0x4C) \
+#define CSID_CSI2_RDIN_IRQ_SET(rdi) ((csid_is_lite(csid) ? 0x3C : 0x4C) \
+ 0x10 * (rdi))
#define CSID_TOP_IRQ_STATUS 0x70
@@ -73,7 +72,7 @@
#define CGC_MODE_DYNAMIC_GATING 0
#define CGC_MODE_ALWAYS_ON 1
-#define CSID_RDI_CFG0(rdi) ((IS_LITE ? 0x200 : 0x300) \
+#define CSID_RDI_CFG0(rdi) ((csid_is_lite(csid) ? 0x200 : 0x300) \
+ 0x100 * (rdi))
#define RDI_CFG0_BYTE_CNTR_EN 0
#define RDI_CFG0_FORMAT_MEASURE_EN 1
@@ -98,32 +97,32 @@
#define RDI_CFG0_PACKING_FORMAT 30
#define RDI_CFG0_ENABLE 31
-#define CSID_RDI_CFG1(rdi) ((IS_LITE ? 0x204 : 0x304)\
+#define CSID_RDI_CFG1(rdi) ((csid_is_lite(csid) ? 0x204 : 0x304)\
+ 0x100 * (rdi))
#define RDI_CFG1_TIMESTAMP_STB_SEL 0
-#define CSID_RDI_CTRL(rdi) ((IS_LITE ? 0x208 : 0x308)\
+#define CSID_RDI_CTRL(rdi) ((csid_is_lite(csid) ? 0x208 : 0x308)\
+ 0x100 * (rdi))
#define RDI_CTRL_HALT_CMD 0
#define HALT_CMD_HALT_AT_FRAME_BOUNDARY 0
#define HALT_CMD_RESUME_AT_FRAME_BOUNDARY 1
#define RDI_CTRL_HALT_MODE 2
-#define CSID_RDI_FRM_DROP_PATTERN(rdi) ((IS_LITE ? 0x20C : 0x30C)\
+#define CSID_RDI_FRM_DROP_PATTERN(rdi) ((csid_is_lite(csid) ? 0x20C : 0x30C)\
+ 0x100 * (rdi))
-#define CSID_RDI_FRM_DROP_PERIOD(rdi) ((IS_LITE ? 0x210 : 0x310)\
+#define CSID_RDI_FRM_DROP_PERIOD(rdi) ((csid_is_lite(csid) ? 0x210 : 0x310)\
+ 0x100 * (rdi))
-#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi) ((IS_LITE ? 0x214 : 0x314)\
+#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi) ((csid_is_lite(csid) ? 0x214 : 0x314)\
+ 0x100 * (rdi))
-#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) ((IS_LITE ? 0x218 : 0x318)\
+#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) ((csid_is_lite(csid) ? 0x218 : 0x318)\
+ 0x100 * (rdi))
-#define CSID_RDI_RPP_PIX_DROP_PATTERN(rdi) ((IS_LITE ? 0x224 : 0x324)\
+#define CSID_RDI_RPP_PIX_DROP_PATTERN(rdi) ((csid_is_lite(csid) ? 0x224 : 0x324)\
+ 0x100 * (rdi))
-#define CSID_RDI_RPP_PIX_DROP_PERIOD(rdi) ((IS_LITE ? 0x228 : 0x328)\
+#define CSID_RDI_RPP_PIX_DROP_PERIOD(rdi) ((csid_is_lite(csid) ? 0x228 : 0x328)\
+ 0x100 * (rdi))
-#define CSID_RDI_RPP_LINE_DROP_PATTERN(rdi) ((IS_LITE ? 0x22C : 0x32C)\
+#define CSID_RDI_RPP_LINE_DROP_PATTERN(rdi) ((csid_is_lite(csid) ? 0x22C : 0x32C)\
+ 0x100 * (rdi))
-#define CSID_RDI_RPP_LINE_DROP_PERIOD(rdi) ((IS_LITE ? 0x230 : 0x330)\
+#define CSID_RDI_RPP_LINE_DROP_PERIOD(rdi) ((csid_is_lite(csid) ? 0x230 : 0x330)\
+ 0x100 * (rdi))
#define CSID_TPG_CTRL 0x600
diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c
index 95873f988f..eb27d69e89 100644
--- a/drivers/media/platform/qcom/camss/camss-csid.c
+++ b/drivers/media/platform/qcom/camss/camss-csid.c
@@ -263,7 +263,7 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable)
/*
* __csid_get_format - Get pointer to format structure
* @csid: CSID device
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @pad: pad from which format is requested
* @which: TRY or ACTIVE format
*
@@ -276,8 +276,7 @@ __csid_get_format(struct csid_device *csid,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&csid->subdev, sd_state,
- pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
return &csid->fmt[pad];
}
@@ -285,7 +284,7 @@ __csid_get_format(struct csid_device *csid,
/*
* csid_try_format - Handle try format by pad subdev method
* @csid: CSID device
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @pad: pad on which format is requested
* @fmt: pointer to v4l2 format structure
* @which: wanted subdev format
@@ -353,7 +352,7 @@ static void csid_try_format(struct csid_device *csid,
/*
* csid_enum_mbus_code - Handle pixel format enumeration
* @sd: CSID V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @code: pointer to v4l2_subdev_mbus_code_enum structure
* return -EINVAL or zero on success
*/
@@ -394,7 +393,7 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd,
/*
* csid_enum_frame_size - Handle frame size enumeration
* @sd: CSID V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fse: pointer to v4l2_subdev_frame_size_enum structure
* return -EINVAL or zero on success
*/
@@ -431,7 +430,7 @@ static int csid_enum_frame_size(struct v4l2_subdev *sd,
/*
* csid_get_format - Handle get format by pads subdev method
* @sd: CSID V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fmt: pointer to v4l2 subdev format structure
*
* Return -EINVAL or zero on success
@@ -455,7 +454,7 @@ static int csid_get_format(struct v4l2_subdev *sd,
/*
* csid_set_format - Handle set format by pads subdev method
* @sd: CSID V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fmt: pointer to v4l2 subdev format structure
*
* Return -EINVAL or zero on success
@@ -897,3 +896,8 @@ void msm_csid_unregister_entity(struct csid_device *csid)
media_entity_cleanup(&csid->subdev.entity);
v4l2_ctrl_handler_free(&csid->ctrls);
}
+
+inline bool csid_is_lite(struct csid_device *csid)
+{
+ return csid->camss->res->csid_res[csid->id].is_lite;
+}
diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h
index 30d94eb2eb..fddccb69da 100644
--- a/drivers/media/platform/qcom/camss/camss-csid.h
+++ b/drivers/media/platform/qcom/camss/camss-csid.h
@@ -215,5 +215,12 @@ extern const struct csid_hw_ops csid_ops_4_1;
extern const struct csid_hw_ops csid_ops_4_7;
extern const struct csid_hw_ops csid_ops_gen2;
+/*
+ * csid_is_lite - Check if CSID is CSID lite.
+ * @csid: CSID Device
+ *
+ * Return whether CSID is CSID lite
+ */
+bool csid_is_lite(struct csid_device *csid);
#endif /* QC_MSM_CAMSS_CSID_H */
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c
index edd573606a..264c99efea 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.c
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.c
@@ -312,7 +312,7 @@ static int csiphy_set_stream(struct v4l2_subdev *sd, int enable)
/*
* __csiphy_get_format - Get pointer to format structure
* @csiphy: CSIPHY device
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @pad: pad from which format is requested
* @which: TRY or ACTIVE format
*
@@ -325,8 +325,7 @@ __csiphy_get_format(struct csiphy_device *csiphy,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&csiphy->subdev, sd_state,
- pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
return &csiphy->fmt[pad];
}
@@ -334,7 +333,7 @@ __csiphy_get_format(struct csiphy_device *csiphy,
/*
* csiphy_try_format - Handle try format by pad subdev method
* @csiphy: CSIPHY device
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @pad: pad on which format is requested
* @fmt: pointer to v4l2 format structure
* @which: wanted subdev format
@@ -381,7 +380,7 @@ static void csiphy_try_format(struct csiphy_device *csiphy,
/*
* csiphy_enum_mbus_code - Handle pixel format enumeration
* @sd: CSIPHY V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @code: pointer to v4l2_subdev_mbus_code_enum structure
* return -EINVAL or zero on success
*/
@@ -414,7 +413,7 @@ static int csiphy_enum_mbus_code(struct v4l2_subdev *sd,
/*
* csiphy_enum_frame_size - Handle frame size enumeration
* @sd: CSIPHY V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fse: pointer to v4l2_subdev_frame_size_enum structure
* return -EINVAL or zero on success
*/
@@ -451,7 +450,7 @@ static int csiphy_enum_frame_size(struct v4l2_subdev *sd,
/*
* csiphy_get_format - Handle get format by pads subdev method
* @sd: CSIPHY V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fmt: pointer to v4l2 subdev format structure
*
* Return -EINVAL or zero on success
@@ -475,7 +474,7 @@ static int csiphy_get_format(struct v4l2_subdev *sd,
/*
* csiphy_set_format - Handle set format by pads subdev method
* @sd: CSIPHY V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fmt: pointer to v4l2 subdev format structure
*
* Return -EINVAL or zero on success
diff --git a/drivers/media/platform/qcom/camss/camss-ispif.c b/drivers/media/platform/qcom/camss/camss-ispif.c
index be9d2f0a10..a12dcc7ff4 100644
--- a/drivers/media/platform/qcom/camss/camss-ispif.c
+++ b/drivers/media/platform/qcom/camss/camss-ispif.c
@@ -270,7 +270,7 @@ static int ispif_vfe_reset(struct ispif_device *ispif, u8 vfe_id)
unsigned long time;
u32 val;
- if (vfe_id > camss->res->vfe_num - 1) {
+ if (vfe_id >= camss->res->vfe_num) {
dev_err(camss->dev,
"Error: asked reset for invalid VFE%d\n", vfe_id);
return -ENOENT;
@@ -866,7 +866,7 @@ static int ispif_set_stream(struct v4l2_subdev *sd, int enable)
/*
* __ispif_get_format - Get pointer to format structure
* @ispif: ISPIF line
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @pad: pad from which format is requested
* @which: TRY or ACTIVE format
*
@@ -879,8 +879,7 @@ __ispif_get_format(struct ispif_line *line,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&line->subdev, sd_state,
- pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
return &line->fmt[pad];
}
@@ -888,7 +887,7 @@ __ispif_get_format(struct ispif_line *line,
/*
* ispif_try_format - Handle try format by pad subdev method
* @ispif: ISPIF line
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @pad: pad on which format is requested
* @fmt: pointer to v4l2 format structure
* @which: wanted subdev format
@@ -936,7 +935,7 @@ static void ispif_try_format(struct ispif_line *line,
/*
* ispif_enum_mbus_code - Handle pixel format enumeration
* @sd: ISPIF V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @code: pointer to v4l2_subdev_mbus_code_enum structure
* return -EINVAL or zero on success
*/
@@ -969,7 +968,7 @@ static int ispif_enum_mbus_code(struct v4l2_subdev *sd,
/*
* ispif_enum_frame_size - Handle frame size enumeration
* @sd: ISPIF V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fse: pointer to v4l2_subdev_frame_size_enum structure
* return -EINVAL or zero on success
*/
@@ -1006,7 +1005,7 @@ static int ispif_enum_frame_size(struct v4l2_subdev *sd,
/*
* ispif_get_format - Handle get format by pads subdev method
* @sd: ISPIF V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fmt: pointer to v4l2 subdev format structure
*
* Return -EINVAL or zero on success
@@ -1030,7 +1029,7 @@ static int ispif_get_format(struct v4l2_subdev *sd,
/*
* ispif_set_format - Handle set format by pads subdev method
* @sd: ISPIF V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fmt: pointer to v4l2 subdev format structure
*
* Return -EINVAL or zero on success
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-170.c b/drivers/media/platform/qcom/camss/camss-vfe-170.c
index 0b211fed12..795ac38153 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-170.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-170.c
@@ -628,42 +628,6 @@ out_unlock:
}
/*
- * vfe_pm_domain_off - Disable power domains specific to this VFE.
- * @vfe: VFE Device
- */
-static void vfe_pm_domain_off(struct vfe_device *vfe)
-{
- struct camss *camss = vfe->camss;
-
- if (vfe->id >= camss->res->vfe_num)
- return;
-
- device_link_del(camss->genpd_link[vfe->id]);
-}
-
-/*
- * vfe_pm_domain_on - Enable power domains specific to this VFE.
- * @vfe: VFE Device
- */
-static int vfe_pm_domain_on(struct vfe_device *vfe)
-{
- struct camss *camss = vfe->camss;
- enum vfe_line_id id = vfe->id;
-
- if (id >= camss->res->vfe_num)
- return 0;
-
- camss->genpd_link[id] = device_link_add(camss->dev, camss->genpd[id],
- DL_FLAG_STATELESS |
- DL_FLAG_PM_RUNTIME |
- DL_FLAG_RPM_ACTIVE);
- if (!camss->genpd_link[id])
- return -EINVAL;
-
- return 0;
-}
-
-/*
* vfe_queue_buffer - Add empty buffer
* @vid: Video device structure
* @buf: Buffer to be enqueued
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-1.c b/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
index 2911e4126e..ef6b34c915 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
@@ -936,7 +936,7 @@ static irqreturn_t vfe_isr(int irq, void *dev)
* vfe_pm_domain_off - Disable power domains specific to this VFE.
* @vfe: VFE Device
*/
-static void vfe_pm_domain_off(struct vfe_device *vfe)
+static void vfe_4_1_pm_domain_off(struct vfe_device *vfe)
{
/* nop */
}
@@ -945,7 +945,7 @@ static void vfe_pm_domain_off(struct vfe_device *vfe)
* vfe_pm_domain_on - Enable power domains specific to this VFE.
* @vfe: VFE Device
*/
-static int vfe_pm_domain_on(struct vfe_device *vfe)
+static int vfe_4_1_pm_domain_on(struct vfe_device *vfe)
{
return 0;
}
@@ -999,8 +999,8 @@ const struct vfe_hw_ops vfe_ops_4_1 = {
.hw_version = vfe_hw_version,
.isr_read = vfe_isr_read,
.isr = vfe_isr,
- .pm_domain_off = vfe_pm_domain_off,
- .pm_domain_on = vfe_pm_domain_on,
+ .pm_domain_off = vfe_4_1_pm_domain_off,
+ .pm_domain_on = vfe_4_1_pm_domain_on,
.reg_update_clear = vfe_reg_update_clear,
.reg_update = vfe_reg_update,
.subdev_init = vfe_subdev_init,
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-7.c b/drivers/media/platform/qcom/camss/camss-vfe-4-7.c
index b65ed0fef5..7655d22a9f 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-4-7.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-4-7.c
@@ -1103,42 +1103,6 @@ static void vfe_isr_read(struct vfe_device *vfe, u32 *value0, u32 *value1)
writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD);
}
-/*
- * vfe_pm_domain_off - Disable power domains specific to this VFE.
- * @vfe: VFE Device
- */
-static void vfe_pm_domain_off(struct vfe_device *vfe)
-{
- struct camss *camss;
-
- if (!vfe)
- return;
-
- camss = vfe->camss;
-
- device_link_del(camss->genpd_link[vfe->id]);
-}
-
-/*
- * vfe_pm_domain_on - Enable power domains specific to this VFE.
- * @vfe: VFE Device
- */
-static int vfe_pm_domain_on(struct vfe_device *vfe)
-{
- struct camss *camss = vfe->camss;
- enum vfe_line_id id = vfe->id;
-
- camss->genpd_link[id] = device_link_add(camss->dev, camss->genpd[id], DL_FLAG_STATELESS |
- DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
-
- if (!camss->genpd_link[id]) {
- dev_err(vfe->camss->dev, "Failed to add VFE#%d to power domain\n", id);
- return -EINVAL;
- }
-
- return 0;
-}
-
static void vfe_violation_read(struct vfe_device *vfe)
{
u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS);
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-8.c b/drivers/media/platform/qcom/camss/camss-vfe-4-8.c
index 7b3805177f..f52fa30f38 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-4-8.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-4-8.c
@@ -1093,37 +1093,6 @@ static void vfe_isr_read(struct vfe_device *vfe, u32 *value0, u32 *value1)
writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD);
}
-/*
- * vfe_pm_domain_off - Disable power domains specific to this VFE.
- * @vfe: VFE Device
- */
-static void vfe_pm_domain_off(struct vfe_device *vfe)
-{
- struct camss *camss = vfe->camss;
-
- device_link_del(camss->genpd_link[vfe->id]);
-}
-
-/*
- * vfe_pm_domain_on - Enable power domains specific to this VFE.
- * @vfe: VFE Device
- */
-static int vfe_pm_domain_on(struct vfe_device *vfe)
-{
- struct camss *camss = vfe->camss;
- enum vfe_line_id id = vfe->id;
-
- camss->genpd_link[id] = device_link_add(camss->dev, camss->genpd[id], DL_FLAG_STATELESS |
- DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
-
- if (!camss->genpd_link[id]) {
- dev_err(vfe->camss->dev, "Failed to add VFE#%d to power domain\n", id);
- return -EINVAL;
- }
-
- return 0;
-}
-
static void vfe_violation_read(struct vfe_device *vfe)
{
u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS);
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-480.c b/drivers/media/platform/qcom/camss/camss-vfe-480.c
index f2368b77fc..dc2735476c 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-480.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-480.c
@@ -15,31 +15,28 @@
#include "camss.h"
#include "camss-vfe.h"
-/* VFE 2/3 are lite and have a different register layout */
-#define IS_LITE (vfe->id >= 2 ? 1 : 0)
-
#define VFE_HW_VERSION (0x00)
-#define VFE_GLOBAL_RESET_CMD (IS_LITE ? 0x0c : 0x1c)
-#define GLOBAL_RESET_HW_AND_REG (IS_LITE ? BIT(1) : BIT(0))
+#define VFE_GLOBAL_RESET_CMD (vfe_is_lite(vfe) ? 0x0c : 0x1c)
+#define GLOBAL_RESET_HW_AND_REG (vfe_is_lite(vfe) ? BIT(1) : BIT(0))
-#define VFE_REG_UPDATE_CMD (IS_LITE ? 0x20 : 0x34)
+#define VFE_REG_UPDATE_CMD (vfe_is_lite(vfe) ? 0x20 : 0x34)
static inline int reg_update_rdi(struct vfe_device *vfe, int n)
{
- return IS_LITE ? BIT(n) : BIT(1 + (n));
+ return vfe_is_lite(vfe) ? BIT(n) : BIT(1 + (n));
}
#define REG_UPDATE_RDI reg_update_rdi
-#define VFE_IRQ_CMD (IS_LITE ? 0x24 : 0x38)
+#define VFE_IRQ_CMD (vfe_is_lite(vfe) ? 0x24 : 0x38)
#define IRQ_CMD_GLOBAL_CLEAR BIT(0)
-#define VFE_IRQ_MASK(n) ((IS_LITE ? 0x28 : 0x3c) + (n) * 4)
-#define IRQ_MASK_0_RESET_ACK (IS_LITE ? BIT(17) : BIT(0))
-#define IRQ_MASK_0_BUS_TOP_IRQ (IS_LITE ? BIT(4) : BIT(7))
-#define VFE_IRQ_CLEAR(n) ((IS_LITE ? 0x34 : 0x48) + (n) * 4)
-#define VFE_IRQ_STATUS(n) ((IS_LITE ? 0x40 : 0x54) + (n) * 4)
+#define VFE_IRQ_MASK(n) ((vfe_is_lite(vfe) ? 0x28 : 0x3c) + (n) * 4)
+#define IRQ_MASK_0_RESET_ACK (vfe_is_lite(vfe) ? BIT(17) : BIT(0))
+#define IRQ_MASK_0_BUS_TOP_IRQ (vfe_is_lite(vfe) ? BIT(4) : BIT(7))
+#define VFE_IRQ_CLEAR(n) ((vfe_is_lite(vfe) ? 0x34 : 0x48) + (n) * 4)
+#define VFE_IRQ_STATUS(n) ((vfe_is_lite(vfe) ? 0x40 : 0x54) + (n) * 4)
-#define BUS_REG_BASE (IS_LITE ? 0x1a00 : 0xaa00)
+#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x1a00 : 0xaa00)
#define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08)
#define WM_CGC_OVERRIDE_ALL (0x3FFFFFF)
@@ -49,13 +46,13 @@ static inline int reg_update_rdi(struct vfe_device *vfe, int n)
#define VFE_BUS_IRQ_MASK(n) (BUS_REG_BASE + 0x18 + (n) * 4)
static inline int bus_irq_mask_0_rdi_rup(struct vfe_device *vfe, int n)
{
- return IS_LITE ? BIT(n) : BIT(3 + (n));
+ return vfe_is_lite(vfe) ? BIT(n) : BIT(3 + (n));
}
#define BUS_IRQ_MASK_0_RDI_RUP bus_irq_mask_0_rdi_rup
static inline int bus_irq_mask_0_comp_done(struct vfe_device *vfe, int n)
{
- return IS_LITE ? BIT(4 + (n)) : BIT(6 + (n));
+ return vfe_is_lite(vfe) ? BIT(4 + (n)) : BIT(6 + (n));
}
#define BUS_IRQ_MASK_0_COMP_DONE bus_irq_mask_0_comp_done
@@ -90,8 +87,8 @@ static inline int bus_irq_mask_0_comp_done(struct vfe_device *vfe, int n)
/* for titan 480, each bus client is hardcoded to a specific path
* and each bus client is part of a hardcoded "comp group"
*/
-#define RDI_WM(n) ((IS_LITE ? 0 : 23) + (n))
-#define RDI_COMP_GROUP(n) ((IS_LITE ? 0 : 11) + (n))
+#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0 : 23) + (n))
+#define RDI_COMP_GROUP(n) ((vfe_is_lite(vfe) ? 0 : 11) + (n))
#define MAX_VFE_OUTPUT_LINES 4
@@ -453,42 +450,6 @@ out_unlock:
}
/*
- * vfe_pm_domain_off - Disable power domains specific to this VFE.
- * @vfe: VFE Device
- */
-static void vfe_pm_domain_off(struct vfe_device *vfe)
-{
- struct camss *camss = vfe->camss;
-
- if (vfe->id >= camss->res->vfe_num)
- return;
-
- device_link_del(camss->genpd_link[vfe->id]);
-}
-
-/*
- * vfe_pm_domain_on - Enable power domains specific to this VFE.
- * @vfe: VFE Device
- */
-static int vfe_pm_domain_on(struct vfe_device *vfe)
-{
- struct camss *camss = vfe->camss;
- enum vfe_line_id id = vfe->id;
-
- if (id >= camss->res->vfe_num)
- return 0;
-
- camss->genpd_link[id] = device_link_add(camss->dev, camss->genpd[id],
- DL_FLAG_STATELESS |
- DL_FLAG_PM_RUNTIME |
- DL_FLAG_RPM_ACTIVE);
- if (!camss->genpd_link[id])
- return -EINVAL;
-
- return 0;
-}
-
-/*
* vfe_queue_buffer - Add empty buffer
* @vid: Video device structure
* @buf: Buffer to be enqueued
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
index 4839e2cedf..2062be668f 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe.c
@@ -14,6 +14,7 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/spinlock_types.h>
#include <linux/spinlock.h>
@@ -474,6 +475,40 @@ void vfe_isr_reset_ack(struct vfe_device *vfe)
complete(&vfe->reset_complete);
}
+/*
+ * vfe_pm_domain_off - Disable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+void vfe_pm_domain_off(struct vfe_device *vfe)
+{
+ if (!vfe->genpd)
+ return;
+
+ device_link_del(vfe->genpd_link);
+ vfe->genpd_link = NULL;
+}
+
+/*
+ * vfe_pm_domain_on - Enable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+int vfe_pm_domain_on(struct vfe_device *vfe)
+{
+ struct camss *camss = vfe->camss;
+
+ if (!vfe->genpd)
+ return 0;
+
+ vfe->genpd_link = device_link_add(camss->dev, vfe->genpd,
+ DL_FLAG_STATELESS |
+ DL_FLAG_PM_RUNTIME |
+ DL_FLAG_RPM_ACTIVE);
+ if (!vfe->genpd_link)
+ return -EINVAL;
+
+ return 0;
+}
+
static int vfe_match_clock_names(struct vfe_device *vfe,
struct camss_clock *clock)
{
@@ -815,7 +850,7 @@ static int vfe_set_stream(struct v4l2_subdev *sd, int enable)
/*
* __vfe_get_format - Get pointer to format structure
* @line: VFE line
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @pad: pad from which format is requested
* @which: TRY or ACTIVE format
*
@@ -828,8 +863,7 @@ __vfe_get_format(struct vfe_line *line,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&line->subdev, sd_state,
- pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
return &line->fmt[pad];
}
@@ -837,7 +871,7 @@ __vfe_get_format(struct vfe_line *line,
/*
* __vfe_get_compose - Get pointer to compose selection structure
* @line: VFE line
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @which: TRY or ACTIVE format
*
* Return pointer to TRY or ACTIVE compose rectangle structure
@@ -848,8 +882,8 @@ __vfe_get_compose(struct vfe_line *line,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_compose(&line->subdev, sd_state,
- MSM_VFE_PAD_SINK);
+ return v4l2_subdev_state_get_compose(sd_state,
+ MSM_VFE_PAD_SINK);
return &line->compose;
}
@@ -857,7 +891,7 @@ __vfe_get_compose(struct vfe_line *line,
/*
* __vfe_get_crop - Get pointer to crop selection structure
* @line: VFE line
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @which: TRY or ACTIVE format
*
* Return pointer to TRY or ACTIVE crop rectangle structure
@@ -868,8 +902,7 @@ __vfe_get_crop(struct vfe_line *line,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_crop(&line->subdev, sd_state,
- MSM_VFE_PAD_SRC);
+ return v4l2_subdev_state_get_crop(sd_state, MSM_VFE_PAD_SRC);
return &line->crop;
}
@@ -877,7 +910,7 @@ __vfe_get_crop(struct vfe_line *line,
/*
* vfe_try_format - Handle try format by pad subdev method
* @line: VFE line
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @pad: pad on which format is requested
* @fmt: pointer to v4l2 format structure
* @which: wanted subdev format
@@ -938,7 +971,7 @@ static void vfe_try_format(struct vfe_line *line,
/*
* vfe_try_compose - Handle try compose selection by pad subdev method
* @line: VFE line
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @rect: pointer to v4l2 rect structure
* @which: wanted subdev format
*/
@@ -977,7 +1010,7 @@ static void vfe_try_compose(struct vfe_line *line,
/*
* vfe_try_crop - Handle try crop selection by pad subdev method
* @line: VFE line
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @rect: pointer to v4l2 rect structure
* @which: wanted subdev format
*/
@@ -1020,7 +1053,7 @@ static void vfe_try_crop(struct vfe_line *line,
/*
* vfe_enum_mbus_code - Handle pixel format enumeration
* @sd: VFE V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @code: pointer to v4l2_subdev_mbus_code_enum structure
*
* return -EINVAL or zero on success
@@ -1054,7 +1087,7 @@ static int vfe_enum_mbus_code(struct v4l2_subdev *sd,
/*
* vfe_enum_frame_size - Handle frame size enumeration
* @sd: VFE V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fse: pointer to v4l2_subdev_frame_size_enum structure
*
* Return -EINVAL or zero on success
@@ -1092,7 +1125,7 @@ static int vfe_enum_frame_size(struct v4l2_subdev *sd,
/*
* vfe_get_format - Handle get format by pads subdev method
* @sd: VFE V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fmt: pointer to v4l2 subdev format structure
*
* Return -EINVAL or zero on success
@@ -1120,7 +1153,7 @@ static int vfe_set_selection(struct v4l2_subdev *sd,
/*
* vfe_set_format - Handle set format by pads subdev method
* @sd: VFE V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @fmt: pointer to v4l2 subdev format structure
*
* Return -EINVAL or zero on success
@@ -1171,7 +1204,7 @@ static int vfe_set_format(struct v4l2_subdev *sd,
/*
* vfe_get_selection - Handle get selection by pads subdev method
* @sd: VFE V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @sel: pointer to v4l2 subdev selection structure
*
* Return -EINVAL or zero on success
@@ -1241,7 +1274,7 @@ static int vfe_get_selection(struct v4l2_subdev *sd,
/*
* vfe_set_selection - Handle set selection by pads subdev method
* @sd: VFE V4L2 subdevice
- * @cfg: V4L2 subdev pad configuration
+ * @sd_state: V4L2 subdev state
* @sel: pointer to v4l2 subdev selection structure
*
* Return -EINVAL or zero on success
@@ -1347,6 +1380,34 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
if (!res->line_num)
return -EINVAL;
+ /* Power domain */
+
+ if (res->pd_name) {
+ vfe->genpd = dev_pm_domain_attach_by_name(camss->dev,
+ res->pd_name);
+ if (IS_ERR(vfe->genpd)) {
+ ret = PTR_ERR(vfe->genpd);
+ return ret;
+ }
+ }
+
+ if (!vfe->genpd && res->has_pd) {
+ /*
+ * Legacy magic index.
+ * Requires
+ * power-domain = <VFE_X>,
+ * <VFE_Y>,
+ * <TITAN_TOP>
+ * id must correspondng to the index of the VFE which must
+ * come before the TOP GDSC. VFE Lite has no individually
+ * collapasible domain which is why id < vfe_num is a valid
+ * check.
+ */
+ vfe->genpd = dev_pm_domain_attach_by_id(camss->dev, id);
+ if (IS_ERR(vfe->genpd))
+ return PTR_ERR(vfe->genpd);
+ }
+
vfe->line_num = res->line_num;
vfe->ops->subdev_init(dev, vfe);
@@ -1470,6 +1531,19 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
}
/*
+ * msm_vfe_genpd_cleanup - Cleanup VFE genpd linkages
+ * @vfe: VFE device
+ */
+void msm_vfe_genpd_cleanup(struct vfe_device *vfe)
+{
+ if (vfe->genpd_link)
+ device_link_del(vfe->genpd_link);
+
+ if (vfe->genpd)
+ dev_pm_domain_detach(vfe->genpd, true);
+}
+
+/*
* vfe_link_setup - Setup VFE connections
* @entity: Pointer to media entity structure
* @local: Pointer to local pad
@@ -1663,3 +1737,8 @@ void msm_vfe_unregister_entities(struct vfe_device *vfe)
media_entity_cleanup(&sd->entity);
}
}
+
+bool vfe_is_lite(struct vfe_device *vfe)
+{
+ return vfe->camss->res->vfe_res[vfe->id].is_lite;
+}
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h
index 09baded0dc..0572c9b08e 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe.h
+++ b/drivers/media/platform/qcom/camss/camss-vfe.h
@@ -150,6 +150,8 @@ struct vfe_device {
const struct vfe_hw_ops_gen1 *ops_gen1;
struct vfe_isr_ops isr_ops;
struct camss_video_ops video_ops;
+ struct device *genpd;
+ struct device_link *genpd_link;
};
struct camss_subdev_resources;
@@ -157,6 +159,8 @@ struct camss_subdev_resources;
int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
const struct camss_subdev_resources *res, u8 id);
+void msm_vfe_genpd_cleanup(struct vfe_device *vfe);
+
int msm_vfe_register_entities(struct vfe_device *vfe,
struct v4l2_device *v4l2_dev);
@@ -201,6 +205,18 @@ int vfe_reset(struct vfe_device *vfe);
*/
int vfe_disable(struct vfe_line *line);
+/*
+ * vfe_pm_domain_off - Disable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+void vfe_pm_domain_off(struct vfe_device *vfe);
+
+/*
+ * vfe_pm_domain_on - Enable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+int vfe_pm_domain_on(struct vfe_device *vfe);
+
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;
@@ -210,4 +226,14 @@ extern const struct vfe_hw_ops vfe_ops_480;
int vfe_get(struct vfe_device *vfe);
void vfe_put(struct vfe_device *vfe);
+/*
+ * vfe_is_lite - Return if VFE is VFE lite.
+ * @vfe: VFE Device
+ *
+ * Some VFE lites have a different register layout.
+ *
+ * Return whether VFE is VFE lite
+ */
+bool vfe_is_lite(struct vfe_device *vfe);
+
#endif /* QC_MSM_CAMSS_VFE_H */
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 8e78dd8d59..58f4be6602 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -278,6 +278,7 @@ static const struct camss_subdev_resources vfe_res_8x96[] = {
.reg = { "vfe0" },
.interrupt = { "vfe0" },
.line_num = 3,
+ .has_pd = true,
.ops = &vfe_ops_4_7
},
@@ -298,6 +299,7 @@ static const struct camss_subdev_resources vfe_res_8x96[] = {
.reg = { "vfe1" },
.interrupt = { "vfe1" },
.line_num = 3,
+ .has_pd = true,
.ops = &vfe_ops_4_7
}
};
@@ -468,6 +470,7 @@ static const struct camss_subdev_resources vfe_res_660[] = {
.reg = { "vfe0" },
.interrupt = { "vfe0" },
.line_num = 3,
+ .has_pd = true,
.ops = &vfe_ops_4_8
},
@@ -491,6 +494,7 @@ static const struct camss_subdev_resources vfe_res_660[] = {
.reg = { "vfe1" },
.interrupt = { "vfe1" },
.line_num = 3,
+ .has_pd = true,
.ops = &vfe_ops_4_8
}
};
@@ -634,6 +638,7 @@ static const struct camss_subdev_resources csid_res_845[] = {
{ 384000000 } },
.reg = { "csid2" },
.interrupt = { "csid2" },
+ .is_lite = true,
.ops = &csid_ops_gen2
}
};
@@ -658,6 +663,7 @@ static const struct camss_subdev_resources vfe_res_845[] = {
.reg = { "vfe0" },
.interrupt = { "vfe0" },
.line_num = 4,
+ .has_pd = true,
.ops = &vfe_ops_170
},
@@ -680,6 +686,7 @@ static const struct camss_subdev_resources vfe_res_845[] = {
.reg = { "vfe1" },
.interrupt = { "vfe1" },
.line_num = 4,
+ .has_pd = true,
.ops = &vfe_ops_170
},
@@ -700,6 +707,7 @@ static const struct camss_subdev_resources vfe_res_845[] = {
{ 384000000 } },
.reg = { "vfe_lite" },
.interrupt = { "vfe_lite" },
+ .is_lite = true,
.line_num = 4,
.ops = &vfe_ops_170
}
@@ -805,6 +813,7 @@ static const struct camss_subdev_resources csid_res_8250[] = {
{ 0 } },
.reg = { "csid2" },
.interrupt = { "csid2" },
+ .is_lite = true,
.ops = &csid_ops_gen2
},
/* CSID3 */
@@ -817,6 +826,7 @@ static const struct camss_subdev_resources csid_res_8250[] = {
{ 0 } },
.reg = { "csid3" },
.interrupt = { "csid3" },
+ .is_lite = true,
.ops = &csid_ops_gen2
}
};
@@ -839,7 +849,9 @@ static const struct camss_subdev_resources vfe_res_8250[] = {
{ 0 } },
.reg = { "vfe0" },
.interrupt = { "vfe0" },
+ .pd_name = "ife0",
.line_num = 3,
+ .has_pd = true,
.ops = &vfe_ops_480
},
/* VFE1 */
@@ -859,7 +871,9 @@ static const struct camss_subdev_resources vfe_res_8250[] = {
{ 0 } },
.reg = { "vfe1" },
.interrupt = { "vfe1" },
+ .pd_name = "ife1",
.line_num = 3,
+ .has_pd = true,
.ops = &vfe_ops_480
},
/* VFE2 (lite) */
@@ -878,6 +892,7 @@ static const struct camss_subdev_resources vfe_res_8250[] = {
{ 0 } },
.reg = { "vfe_lite0" },
.interrupt = { "vfe_lite0" },
+ .is_lite = true,
.line_num = 4,
.ops = &vfe_ops_480
},
@@ -897,6 +912,7 @@ static const struct camss_subdev_resources vfe_res_8250[] = {
{ 0 } },
.reg = { "vfe_lite1" },
.interrupt = { "vfe_lite1" },
+ .is_lite = true,
.line_num = 4,
.ops = &vfe_ops_480
},
@@ -1196,7 +1212,7 @@ static int camss_init_subdevices(struct camss *camss)
}
/* note: SM8250 requires VFE to be initialized before CSID */
- for (i = 0; i < camss->vfe_total_num; i++) {
+ for (i = 0; i < camss->res->vfe_num; i++) {
ret = msm_vfe_subdev_init(camss, &camss->vfe[i],
&res->vfe_res[i], i);
if (ret < 0) {
@@ -1268,7 +1284,7 @@ static int camss_register_entities(struct camss *camss)
goto err_reg_ispif;
}
- for (i = 0; i < camss->vfe_total_num; i++) {
+ for (i = 0; i < camss->res->vfe_num; i++) {
ret = msm_vfe_register_entities(&camss->vfe[i],
&camss->v4l2_dev);
if (ret < 0) {
@@ -1340,7 +1356,7 @@ static int camss_register_entities(struct camss *camss)
}
} else {
for (i = 0; i < camss->res->csid_num; i++)
- for (k = 0; k < camss->vfe_total_num; k++)
+ for (k = 0; k < camss->res->vfe_num; k++)
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;
@@ -1364,7 +1380,7 @@ static int camss_register_entities(struct camss *camss)
return 0;
err_link:
- i = camss->vfe_total_num;
+ i = camss->res->vfe_num;
err_reg_vfe:
for (i--; i >= 0; i--)
msm_vfe_unregister_entities(&camss->vfe[i]);
@@ -1403,7 +1419,7 @@ static void camss_unregister_entities(struct camss *camss)
msm_ispif_unregister_entities(camss->ispif);
- for (i = 0; i < camss->vfe_total_num; i++)
+ for (i = 0; i < camss->res->vfe_num; i++)
msm_vfe_unregister_entities(&camss->vfe[i]);
}
@@ -1478,7 +1494,9 @@ static const struct media_device_ops camss_media_ops = {
static int camss_configure_pd(struct camss *camss)
{
+ const struct camss_resources *res = camss->res;
struct device *dev = camss->dev;
+ int vfepd_num;
int i;
int ret;
@@ -1498,45 +1516,60 @@ static int camss_configure_pd(struct camss *camss)
if (camss->genpd_num == 1)
return 0;
- camss->genpd = devm_kmalloc_array(dev, camss->genpd_num,
- sizeof(*camss->genpd), GFP_KERNEL);
- if (!camss->genpd)
- return -ENOMEM;
+ /* count the # of VFEs which have flagged power-domain */
+ for (vfepd_num = i = 0; i < camss->res->vfe_num; i++) {
+ if (res->vfe_res[i].has_pd)
+ vfepd_num++;
+ }
- camss->genpd_link = devm_kmalloc_array(dev, camss->genpd_num,
- sizeof(*camss->genpd_link),
- GFP_KERNEL);
- if (!camss->genpd_link)
- return -ENOMEM;
+ /*
+ * If the number of power-domains is greater than the number of VFEs
+ * then the additional power-domain is for the entire CAMSS block.
+ */
+ if (!(camss->genpd_num > vfepd_num))
+ return 0;
/*
- * VFE power domains are in the beginning of the list, and while all
- * power domains should be attached, only if TITAN_TOP power domain is
- * found in the list, it should be linked over here.
+ * If a power-domain name is defined try to use it.
+ * It is possible we are running a new kernel with an old dtb so
+ * fallback to indexes even if a pd_name is defined but not found.
*/
- for (i = 0; i < camss->genpd_num; i++) {
- camss->genpd[i] = dev_pm_domain_attach_by_id(camss->dev, i);
- if (IS_ERR(camss->genpd[i])) {
- ret = PTR_ERR(camss->genpd[i]);
+ if (camss->res->pd_name) {
+ camss->genpd = dev_pm_domain_attach_by_name(camss->dev,
+ camss->res->pd_name);
+ if (IS_ERR(camss->genpd)) {
+ ret = PTR_ERR(camss->genpd);
goto fail_pm;
}
}
- if (i > camss->res->vfe_num) {
- camss->genpd_link[i - 1] = device_link_add(camss->dev, camss->genpd[i - 1],
- DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME |
- DL_FLAG_RPM_ACTIVE);
- if (!camss->genpd_link[i - 1]) {
- ret = -EINVAL;
- goto fail_pm;
- }
+ if (!camss->genpd) {
+ /*
+ * Legacy magic index. TITAN_TOP GDSC must be the last
+ * item in the power-domain list.
+ */
+ camss->genpd = dev_pm_domain_attach_by_id(camss->dev,
+ camss->genpd_num - 1);
+ }
+ if (IS_ERR_OR_NULL(camss->genpd)) {
+ if (!camss->genpd)
+ ret = -ENODEV;
+ else
+ ret = PTR_ERR(camss->genpd);
+ goto fail_pm;
+ }
+ camss->genpd_link = device_link_add(camss->dev, camss->genpd,
+ DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME |
+ DL_FLAG_RPM_ACTIVE);
+ if (!camss->genpd_link) {
+ ret = -EINVAL;
+ goto fail_pm;
}
return 0;
fail_pm:
- for (--i ; i >= 0; i--)
- dev_pm_domain_detach(camss->genpd[i], true);
+ dev_pm_domain_detach(camss->genpd, true);
return ret;
}
@@ -1558,18 +1591,25 @@ static int camss_icc_get(struct camss *camss)
return 0;
}
-static void camss_genpd_cleanup(struct camss *camss)
+static void camss_genpd_subdevice_cleanup(struct camss *camss)
{
int i;
+ for (i = 0; i < camss->res->vfe_num; i++)
+ msm_vfe_genpd_cleanup(&camss->vfe[i]);
+}
+
+static void camss_genpd_cleanup(struct camss *camss)
+{
if (camss->genpd_num == 1)
return;
- if (camss->genpd_num > camss->res->vfe_num)
- device_link_del(camss->genpd_link[camss->genpd_num - 1]);
+ camss_genpd_subdevice_cleanup(camss);
+
+ if (camss->genpd_link)
+ device_link_del(camss->genpd_link);
- for (i = 0; i < camss->genpd_num; i++)
- dev_pm_domain_detach(camss->genpd[i], true);
+ dev_pm_domain_detach(camss->genpd, true);
}
/*
@@ -1612,8 +1652,7 @@ static int camss_probe(struct platform_device *pdev)
return -ENOMEM;
}
- camss->vfe_total_num = camss->res->vfe_num + camss->res->vfe_lite_num;
- camss->vfe = devm_kcalloc(dev, camss->vfe_total_num,
+ camss->vfe = devm_kcalloc(dev, camss->res->vfe_num,
sizeof(*camss->vfe), GFP_KERNEL);
if (!camss->vfe)
return -ENOMEM;
@@ -1771,12 +1810,12 @@ static const struct camss_resources sdm845_resources = {
.vfe_res = vfe_res_845,
.csiphy_num = ARRAY_SIZE(csiphy_res_845),
.csid_num = ARRAY_SIZE(csid_res_845),
- .vfe_num = 2,
- .vfe_lite_num = 1,
+ .vfe_num = ARRAY_SIZE(vfe_res_845),
};
static const struct camss_resources sm8250_resources = {
.version = CAMSS_8250,
+ .pd_name = "top",
.csiphy_res = csiphy_res_8250,
.csid_res = csid_res_8250,
.vfe_res = vfe_res_8250,
@@ -1784,8 +1823,7 @@ static const struct camss_resources sm8250_resources = {
.icc_path_num = ARRAY_SIZE(icc_res_sm8250),
.csiphy_num = ARRAY_SIZE(csiphy_res_8250),
.csid_num = ARRAY_SIZE(csid_res_8250),
- .vfe_num = 2,
- .vfe_lite_num = 2,
+ .vfe_num = ARRAY_SIZE(vfe_res_8250),
};
static const struct of_device_id camss_dt_match[] = {
diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
index 8acad7321c..a0c2dcc779 100644
--- a/drivers/media/platform/qcom/camss/camss.h
+++ b/drivers/media/platform/qcom/camss/camss.h
@@ -48,7 +48,10 @@ struct camss_subdev_resources {
u32 clock_rate[CAMSS_RES_MAX][CAMSS_RES_MAX];
char *reg[CAMSS_RES_MAX];
char *interrupt[CAMSS_RES_MAX];
+ char *pd_name;
u8 line_num;
+ bool has_pd;
+ bool is_lite;
const void *ops;
};
@@ -83,6 +86,7 @@ enum icc_count {
struct camss_resources {
enum camss_version version;
+ const char *pd_name;
const struct camss_subdev_resources *csiphy_res;
const struct camss_subdev_resources *csid_res;
const struct camss_subdev_resources *ispif_res;
@@ -92,7 +96,6 @@ struct camss_resources {
const unsigned int csiphy_num;
const unsigned int csid_num;
const unsigned int vfe_num;
- const unsigned int vfe_lite_num;
};
struct camss {
@@ -106,11 +109,10 @@ struct camss {
struct vfe_device *vfe;
atomic_t ref_count;
int genpd_num;
- struct device **genpd;
- struct device_link **genpd_link;
+ struct device *genpd;
+ struct device_link *genpd_link;
struct icc_path *icc_path[ICC_SM8250_COUNT];
const struct camss_resources *res;
- unsigned int vfe_total_num;
};
struct camss_camera_interface {