diff options
Diffstat (limited to 'drivers/media/platform/qcom/camss/camss-vfe.c')
-rw-r--r-- | drivers/media/platform/qcom/camss/camss-vfe.c | 115 |
1 files changed, 97 insertions, 18 deletions
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; +} |