diff options
Diffstat (limited to 'drivers/media/platform/qcom')
19 files changed, 385 insertions, 240 deletions
diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c index cc11fbfdae13..a1637b78568b 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.c +++ b/drivers/media/platform/qcom/camss/camss-csid.c @@ -156,11 +156,9 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) int ret; if (on) { - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) return ret; - } ret = regulator_enable(csid->vdda); if (ret < 0) { @@ -247,12 +245,13 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) */ static struct v4l2_mbus_framefmt * __csid_get_format(struct csid_device *csid, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, unsigned int pad, enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&csid->subdev, cfg, pad); + return v4l2_subdev_get_try_format(&csid->subdev, sd_state, + pad); return &csid->fmt[pad]; } @@ -266,7 +265,7 @@ __csid_get_format(struct csid_device *csid, * @which: wanted subdev format */ static void csid_try_format(struct csid_device *csid, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) @@ -299,7 +298,7 @@ static void csid_try_format(struct csid_device *csid, /* keep pad formats in sync */ u32 code = fmt->code; - *fmt = *__csid_get_format(csid, cfg, + *fmt = *__csid_get_format(csid, sd_state, MSM_CSID_PAD_SINK, which); fmt->code = csid->ops->src_pad_code(csid, fmt->code, 0, code); } else { @@ -333,7 +332,7 @@ static void csid_try_format(struct csid_device *csid, * return -EINVAL or zero on success */ static int csid_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) { struct csid_device *csid = v4l2_get_subdevdata(sd); @@ -347,7 +346,7 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, if (csid->testgen_mode->cur.val == 0) { struct v4l2_mbus_framefmt *sink_fmt; - sink_fmt = __csid_get_format(csid, cfg, + sink_fmt = __csid_get_format(csid, sd_state, MSM_CSID_PAD_SINK, code->which); @@ -374,7 +373,7 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, * return -EINVAL or zero on success */ static int csid_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_size_enum *fse) { struct csid_device *csid = v4l2_get_subdevdata(sd); @@ -386,7 +385,7 @@ static int csid_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = 1; format.height = 1; - csid_try_format(csid, cfg, fse->pad, &format, fse->which); + csid_try_format(csid, sd_state, fse->pad, &format, fse->which); fse->min_width = format.width; fse->min_height = format.height; @@ -396,7 +395,7 @@ static int csid_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = -1; format.height = -1; - csid_try_format(csid, cfg, fse->pad, &format, fse->which); + csid_try_format(csid, sd_state, fse->pad, &format, fse->which); fse->max_width = format.width; fse->max_height = format.height; @@ -412,13 +411,13 @@ static int csid_enum_frame_size(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int csid_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { struct csid_device *csid = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - format = __csid_get_format(csid, cfg, fmt->pad, fmt->which); + format = __csid_get_format(csid, sd_state, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; @@ -436,26 +435,26 @@ static int csid_get_format(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int csid_set_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { struct csid_device *csid = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - format = __csid_get_format(csid, cfg, fmt->pad, fmt->which); + format = __csid_get_format(csid, sd_state, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; - csid_try_format(csid, cfg, fmt->pad, &fmt->format, fmt->which); + csid_try_format(csid, sd_state, fmt->pad, &fmt->format, fmt->which); *format = fmt->format; /* Propagate the format from sink to source */ if (fmt->pad == MSM_CSID_PAD_SINK) { - format = __csid_get_format(csid, cfg, MSM_CSID_PAD_SRC, + format = __csid_get_format(csid, sd_state, MSM_CSID_PAD_SRC, fmt->which); *format = fmt->format; - csid_try_format(csid, cfg, MSM_CSID_PAD_SRC, format, + csid_try_format(csid, sd_state, MSM_CSID_PAD_SRC, format, fmt->which); } @@ -484,7 +483,7 @@ static int csid_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } }; - return csid_set_format(sd, fh ? fh->pad : NULL, &format); + return csid_set_format(sd, fh ? fh->state : NULL, &format); } /* @@ -566,8 +565,7 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, /* Memory */ - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res->reg[0]); - csid->base = devm_ioremap_resource(dev, r); + csid->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]); if (IS_ERR(csid->base)) return PTR_ERR(csid->base); @@ -584,14 +582,13 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, snprintf(csid->irq_name, sizeof(csid->irq_name), "%s_%s%d", dev_name(dev), MSM_CSID_NAME, csid->id); ret = devm_request_irq(dev, csid->irq, csid->ops->isr, - IRQF_TRIGGER_RISING, csid->irq_name, csid); + IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN, + csid->irq_name, csid); if (ret < 0) { dev_err(dev, "request_irq failed: %d\n", ret); return ret; } - disable_irq(csid->irq); - /* Clocks */ csid->nclocks = 0; diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c index b3c3bf19e522..24eec16197e7 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c @@ -197,11 +197,9 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) if (on) { int ret; - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) return ret; - } ret = csiphy_set_clock_rates(csiphy); if (ret < 0) { @@ -340,12 +338,13 @@ static int csiphy_set_stream(struct v4l2_subdev *sd, int enable) */ static struct v4l2_mbus_framefmt * __csiphy_get_format(struct csiphy_device *csiphy, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, unsigned int pad, enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&csiphy->subdev, cfg, pad); + return v4l2_subdev_get_try_format(&csiphy->subdev, sd_state, + pad); return &csiphy->fmt[pad]; } @@ -359,7 +358,7 @@ __csiphy_get_format(struct csiphy_device *csiphy, * @which: wanted subdev format */ static void csiphy_try_format(struct csiphy_device *csiphy, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) @@ -389,7 +388,8 @@ static void csiphy_try_format(struct csiphy_device *csiphy, case MSM_CSIPHY_PAD_SRC: /* Set and return a format same as sink pad */ - *fmt = *__csiphy_get_format(csiphy, cfg, MSM_CSID_PAD_SINK, + *fmt = *__csiphy_get_format(csiphy, sd_state, + MSM_CSID_PAD_SINK, which); break; @@ -404,7 +404,7 @@ static void csiphy_try_format(struct csiphy_device *csiphy, * return -EINVAL or zero on success */ static int csiphy_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) { struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); @@ -419,7 +419,8 @@ static int csiphy_enum_mbus_code(struct v4l2_subdev *sd, if (code->index > 0) return -EINVAL; - format = __csiphy_get_format(csiphy, cfg, MSM_CSIPHY_PAD_SINK, + format = __csiphy_get_format(csiphy, sd_state, + MSM_CSIPHY_PAD_SINK, code->which); code->code = format->code; @@ -436,7 +437,7 @@ static int csiphy_enum_mbus_code(struct v4l2_subdev *sd, * return -EINVAL or zero on success */ static int csiphy_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_size_enum *fse) { struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); @@ -448,7 +449,7 @@ static int csiphy_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = 1; format.height = 1; - csiphy_try_format(csiphy, cfg, fse->pad, &format, fse->which); + csiphy_try_format(csiphy, sd_state, fse->pad, &format, fse->which); fse->min_width = format.width; fse->min_height = format.height; @@ -458,7 +459,7 @@ static int csiphy_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = -1; format.height = -1; - csiphy_try_format(csiphy, cfg, fse->pad, &format, fse->which); + csiphy_try_format(csiphy, sd_state, fse->pad, &format, fse->which); fse->max_width = format.width; fse->max_height = format.height; @@ -474,13 +475,13 @@ static int csiphy_enum_frame_size(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int csiphy_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - format = __csiphy_get_format(csiphy, cfg, fmt->pad, fmt->which); + format = __csiphy_get_format(csiphy, sd_state, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; @@ -498,26 +499,29 @@ static int csiphy_get_format(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int csiphy_set_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - format = __csiphy_get_format(csiphy, cfg, fmt->pad, fmt->which); + format = __csiphy_get_format(csiphy, sd_state, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; - csiphy_try_format(csiphy, cfg, fmt->pad, &fmt->format, fmt->which); + csiphy_try_format(csiphy, sd_state, fmt->pad, &fmt->format, + fmt->which); *format = fmt->format; /* Propagate the format from sink to source */ if (fmt->pad == MSM_CSIPHY_PAD_SINK) { - format = __csiphy_get_format(csiphy, cfg, MSM_CSIPHY_PAD_SRC, + format = __csiphy_get_format(csiphy, sd_state, + MSM_CSIPHY_PAD_SRC, fmt->which); *format = fmt->format; - csiphy_try_format(csiphy, cfg, MSM_CSIPHY_PAD_SRC, format, + csiphy_try_format(csiphy, sd_state, MSM_CSIPHY_PAD_SRC, + format, fmt->which); } @@ -547,7 +551,7 @@ static int csiphy_init_formats(struct v4l2_subdev *sd, } }; - return csiphy_set_format(sd, fh ? fh->pad : NULL, &format); + return csiphy_set_format(sd, fh ? fh->state : NULL, &format); } /* @@ -591,16 +595,14 @@ int msm_csiphy_subdev_init(struct camss *camss, /* Memory */ - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res->reg[0]); - csiphy->base = devm_ioremap_resource(dev, r); + csiphy->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]); if (IS_ERR(csiphy->base)) return PTR_ERR(csiphy->base); if (camss->version == CAMSS_8x16 || camss->version == CAMSS_8x96) { - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, - res->reg[1]); - csiphy->base_clk_mux = devm_ioremap_resource(dev, r); + csiphy->base_clk_mux = + devm_platform_ioremap_resource_byname(pdev, res->reg[1]); if (IS_ERR(csiphy->base_clk_mux)) return PTR_ERR(csiphy->base_clk_mux); } else { @@ -621,14 +623,13 @@ int msm_csiphy_subdev_init(struct camss *camss, dev_name(dev), MSM_CSIPHY_NAME, csiphy->id); ret = devm_request_irq(dev, csiphy->irq, csiphy->ops->isr, - IRQF_TRIGGER_RISING, csiphy->irq_name, csiphy); + IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN, + csiphy->irq_name, csiphy); if (ret < 0) { dev_err(dev, "request_irq failed: %d\n", ret); return ret; } - disable_irq(csiphy->irq); - /* Clocks */ csiphy->nclocks = 0; diff --git a/drivers/media/platform/qcom/camss/camss-ispif.c b/drivers/media/platform/qcom/camss/camss-ispif.c index 37611c8861da..ba5d65f6ef34 100644 --- a/drivers/media/platform/qcom/camss/camss-ispif.c +++ b/drivers/media/platform/qcom/camss/camss-ispif.c @@ -372,11 +372,9 @@ static int ispif_set_power(struct v4l2_subdev *sd, int on) goto exit; } - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) goto exit; - } ret = camss_enable_clocks(ispif->nclocks, ispif->clock, dev); if (ret < 0) { @@ -876,12 +874,13 @@ static int ispif_set_stream(struct v4l2_subdev *sd, int enable) */ static struct v4l2_mbus_framefmt * __ispif_get_format(struct ispif_line *line, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, unsigned int pad, enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&line->subdev, cfg, pad); + return v4l2_subdev_get_try_format(&line->subdev, sd_state, + pad); return &line->fmt[pad]; } @@ -895,7 +894,7 @@ __ispif_get_format(struct ispif_line *line, * @which: wanted subdev format */ static void ispif_try_format(struct ispif_line *line, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) @@ -925,7 +924,7 @@ static void ispif_try_format(struct ispif_line *line, case MSM_ISPIF_PAD_SRC: /* Set and return a format same as sink pad */ - *fmt = *__ispif_get_format(line, cfg, MSM_ISPIF_PAD_SINK, + *fmt = *__ispif_get_format(line, sd_state, MSM_ISPIF_PAD_SINK, which); break; @@ -942,7 +941,7 @@ static void ispif_try_format(struct ispif_line *line, * return -EINVAL or zero on success */ static int ispif_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) { struct ispif_line *line = v4l2_get_subdevdata(sd); @@ -957,7 +956,8 @@ static int ispif_enum_mbus_code(struct v4l2_subdev *sd, if (code->index > 0) return -EINVAL; - format = __ispif_get_format(line, cfg, MSM_ISPIF_PAD_SINK, + format = __ispif_get_format(line, sd_state, + MSM_ISPIF_PAD_SINK, code->which); code->code = format->code; @@ -974,7 +974,7 @@ static int ispif_enum_mbus_code(struct v4l2_subdev *sd, * return -EINVAL or zero on success */ static int ispif_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_size_enum *fse) { struct ispif_line *line = v4l2_get_subdevdata(sd); @@ -986,7 +986,7 @@ static int ispif_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = 1; format.height = 1; - ispif_try_format(line, cfg, fse->pad, &format, fse->which); + ispif_try_format(line, sd_state, fse->pad, &format, fse->which); fse->min_width = format.width; fse->min_height = format.height; @@ -996,7 +996,7 @@ static int ispif_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = -1; format.height = -1; - ispif_try_format(line, cfg, fse->pad, &format, fse->which); + ispif_try_format(line, sd_state, fse->pad, &format, fse->which); fse->max_width = format.width; fse->max_height = format.height; @@ -1012,13 +1012,13 @@ static int ispif_enum_frame_size(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int ispif_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { struct ispif_line *line = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - format = __ispif_get_format(line, cfg, fmt->pad, fmt->which); + format = __ispif_get_format(line, sd_state, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; @@ -1036,26 +1036,26 @@ static int ispif_get_format(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int ispif_set_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { struct ispif_line *line = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - format = __ispif_get_format(line, cfg, fmt->pad, fmt->which); + format = __ispif_get_format(line, sd_state, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; - ispif_try_format(line, cfg, fmt->pad, &fmt->format, fmt->which); + ispif_try_format(line, sd_state, fmt->pad, &fmt->format, fmt->which); *format = fmt->format; /* Propagate the format from sink to source */ if (fmt->pad == MSM_ISPIF_PAD_SINK) { - format = __ispif_get_format(line, cfg, MSM_ISPIF_PAD_SRC, + format = __ispif_get_format(line, sd_state, MSM_ISPIF_PAD_SRC, fmt->which); *format = fmt->format; - ispif_try_format(line, cfg, MSM_ISPIF_PAD_SRC, format, + ispif_try_format(line, sd_state, MSM_ISPIF_PAD_SRC, format, fmt->which); } @@ -1084,7 +1084,7 @@ static int ispif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } }; - return ispif_set_format(sd, fh ? fh->pad : NULL, &format); + return ispif_set_format(sd, fh ? fh->state : NULL, &format); } /* @@ -1143,13 +1143,11 @@ int msm_ispif_subdev_init(struct camss *camss, /* Memory */ - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res->reg[0]); - ispif->base = devm_ioremap_resource(dev, r); + ispif->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]); if (IS_ERR(ispif->base)) return PTR_ERR(ispif->base); - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res->reg[1]); - ispif->base_clk_mux = devm_ioremap_resource(dev, r); + ispif->base_clk_mux = devm_platform_ioremap_resource_byname(pdev, res->reg[1]); if (IS_ERR(ispif->base_clk_mux)) return PTR_ERR(ispif->base_clk_mux); diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 15695fd466c4..e0f3a36f3f3f 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -584,9 +584,9 @@ static int vfe_get(struct vfe_device *vfe) if (ret < 0) goto error_pm_domain; - ret = pm_runtime_get_sync(vfe->camss->dev); + ret = pm_runtime_resume_and_get(vfe->camss->dev); if (ret < 0) - goto error_pm_runtime_get; + goto error_domain_off; ret = vfe_set_clock_rates(vfe); if (ret < 0) @@ -620,6 +620,7 @@ error_reset: error_pm_runtime_get: pm_runtime_put_sync(vfe->camss->dev); +error_domain_off: vfe->ops->pm_domain_off(vfe); error_pm_domain: @@ -762,12 +763,13 @@ static int vfe_set_stream(struct v4l2_subdev *sd, int enable) */ static struct v4l2_mbus_framefmt * __vfe_get_format(struct vfe_line *line, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, unsigned int pad, enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&line->subdev, cfg, pad); + return v4l2_subdev_get_try_format(&line->subdev, sd_state, + pad); return &line->fmt[pad]; } @@ -782,11 +784,11 @@ __vfe_get_format(struct vfe_line *line, */ static struct v4l2_rect * __vfe_get_compose(struct vfe_line *line, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_compose(&line->subdev, cfg, + return v4l2_subdev_get_try_compose(&line->subdev, sd_state, MSM_VFE_PAD_SINK); return &line->compose; @@ -802,11 +804,11 @@ __vfe_get_compose(struct vfe_line *line, */ static struct v4l2_rect * __vfe_get_crop(struct vfe_line *line, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_crop(&line->subdev, cfg, + return v4l2_subdev_get_try_crop(&line->subdev, sd_state, MSM_VFE_PAD_SRC); return &line->crop; @@ -821,7 +823,7 @@ __vfe_get_crop(struct vfe_line *line, * @which: wanted subdev format */ static void vfe_try_format(struct vfe_line *line, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) @@ -853,14 +855,15 @@ static void vfe_try_format(struct vfe_line *line, /* Set and return a format same as sink pad */ code = fmt->code; - *fmt = *__vfe_get_format(line, cfg, MSM_VFE_PAD_SINK, which); + *fmt = *__vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, + which); fmt->code = vfe_src_pad_code(line, fmt->code, 0, code); if (line->id == VFE_LINE_PIX) { struct v4l2_rect *rect; - rect = __vfe_get_crop(line, cfg, which); + rect = __vfe_get_crop(line, sd_state, which); fmt->width = rect->width; fmt->height = rect->height; @@ -880,13 +883,13 @@ static void vfe_try_format(struct vfe_line *line, * @which: wanted subdev format */ static void vfe_try_compose(struct vfe_line *line, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_rect *rect, enum v4l2_subdev_format_whence which) { struct v4l2_mbus_framefmt *fmt; - fmt = __vfe_get_format(line, cfg, MSM_VFE_PAD_SINK, which); + fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, which); if (rect->width > fmt->width) rect->width = fmt->width; @@ -919,13 +922,13 @@ static void vfe_try_compose(struct vfe_line *line, * @which: wanted subdev format */ static void vfe_try_crop(struct vfe_line *line, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_rect *rect, enum v4l2_subdev_format_whence which) { struct v4l2_rect *compose; - compose = __vfe_get_compose(line, cfg, which); + compose = __vfe_get_compose(line, sd_state, which); if (rect->width > compose->width) rect->width = compose->width; @@ -963,7 +966,7 @@ static void vfe_try_crop(struct vfe_line *line, * return -EINVAL or zero on success */ static int vfe_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) { struct vfe_line *line = v4l2_get_subdevdata(sd); @@ -976,7 +979,7 @@ static int vfe_enum_mbus_code(struct v4l2_subdev *sd, } else { struct v4l2_mbus_framefmt *sink_fmt; - sink_fmt = __vfe_get_format(line, cfg, MSM_VFE_PAD_SINK, + sink_fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, code->which); code->code = vfe_src_pad_code(line, sink_fmt->code, @@ -997,7 +1000,7 @@ static int vfe_enum_mbus_code(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int vfe_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_size_enum *fse) { struct vfe_line *line = v4l2_get_subdevdata(sd); @@ -1009,7 +1012,7 @@ static int vfe_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = 1; format.height = 1; - vfe_try_format(line, cfg, fse->pad, &format, fse->which); + vfe_try_format(line, sd_state, fse->pad, &format, fse->which); fse->min_width = format.width; fse->min_height = format.height; @@ -1019,7 +1022,7 @@ static int vfe_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = -1; format.height = -1; - vfe_try_format(line, cfg, fse->pad, &format, fse->which); + vfe_try_format(line, sd_state, fse->pad, &format, fse->which); fse->max_width = format.width; fse->max_height = format.height; @@ -1035,13 +1038,13 @@ static int vfe_enum_frame_size(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int vfe_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { struct vfe_line *line = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - format = __vfe_get_format(line, cfg, fmt->pad, fmt->which); + format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; @@ -1051,7 +1054,7 @@ static int vfe_get_format(struct v4l2_subdev *sd, } static int vfe_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_selection *sel); /* @@ -1063,17 +1066,17 @@ static int vfe_set_selection(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int vfe_set_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { struct vfe_line *line = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - format = __vfe_get_format(line, cfg, fmt->pad, fmt->which); + format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; - vfe_try_format(line, cfg, fmt->pad, &fmt->format, fmt->which); + vfe_try_format(line, sd_state, fmt->pad, &fmt->format, fmt->which); *format = fmt->format; if (fmt->pad == MSM_VFE_PAD_SINK) { @@ -1081,11 +1084,11 @@ static int vfe_set_format(struct v4l2_subdev *sd, int ret; /* Propagate the format from sink to source */ - format = __vfe_get_format(line, cfg, MSM_VFE_PAD_SRC, + format = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SRC, fmt->which); *format = fmt->format; - vfe_try_format(line, cfg, MSM_VFE_PAD_SRC, format, + vfe_try_format(line, sd_state, MSM_VFE_PAD_SRC, format, fmt->which); if (line->id != VFE_LINE_PIX) @@ -1097,7 +1100,7 @@ static int vfe_set_format(struct v4l2_subdev *sd, sel.target = V4L2_SEL_TGT_COMPOSE; sel.r.width = fmt->format.width; sel.r.height = fmt->format.height; - ret = vfe_set_selection(sd, cfg, &sel); + ret = vfe_set_selection(sd, sd_state, &sel); if (ret < 0) return ret; } @@ -1114,7 +1117,7 @@ static int vfe_set_format(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int vfe_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_selection *sel) { struct vfe_line *line = v4l2_get_subdevdata(sd); @@ -1130,7 +1133,7 @@ static int vfe_get_selection(struct v4l2_subdev *sd, case V4L2_SEL_TGT_COMPOSE_BOUNDS: fmt.pad = sel->pad; fmt.which = sel->which; - ret = vfe_get_format(sd, cfg, &fmt); + ret = vfe_get_format(sd, sd_state, &fmt); if (ret < 0) return ret; @@ -1140,7 +1143,7 @@ static int vfe_get_selection(struct v4l2_subdev *sd, sel->r.height = fmt.format.height; break; case V4L2_SEL_TGT_COMPOSE: - rect = __vfe_get_compose(line, cfg, sel->which); + rect = __vfe_get_compose(line, sd_state, sel->which); if (rect == NULL) return -EINVAL; @@ -1152,7 +1155,7 @@ static int vfe_get_selection(struct v4l2_subdev *sd, else if (sel->pad == MSM_VFE_PAD_SRC) switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - rect = __vfe_get_compose(line, cfg, sel->which); + rect = __vfe_get_compose(line, sd_state, sel->which); if (rect == NULL) return -EINVAL; @@ -1162,7 +1165,7 @@ static int vfe_get_selection(struct v4l2_subdev *sd, sel->r.height = rect->height; break; case V4L2_SEL_TGT_CROP: - rect = __vfe_get_crop(line, cfg, sel->which); + rect = __vfe_get_crop(line, sd_state, sel->which); if (rect == NULL) return -EINVAL; @@ -1184,7 +1187,7 @@ static int vfe_get_selection(struct v4l2_subdev *sd, * Return -EINVAL or zero on success */ static int vfe_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_selection *sel) { struct vfe_line *line = v4l2_get_subdevdata(sd); @@ -1198,11 +1201,11 @@ static int vfe_set_selection(struct v4l2_subdev *sd, sel->pad == MSM_VFE_PAD_SINK) { struct v4l2_subdev_selection crop = { 0 }; - rect = __vfe_get_compose(line, cfg, sel->which); + rect = __vfe_get_compose(line, sd_state, sel->which); if (rect == NULL) return -EINVAL; - vfe_try_compose(line, cfg, &sel->r, sel->which); + vfe_try_compose(line, sd_state, &sel->r, sel->which); *rect = sel->r; /* Reset source crop selection */ @@ -1210,28 +1213,28 @@ static int vfe_set_selection(struct v4l2_subdev *sd, crop.pad = MSM_VFE_PAD_SRC; crop.target = V4L2_SEL_TGT_CROP; crop.r = *rect; - ret = vfe_set_selection(sd, cfg, &crop); + ret = vfe_set_selection(sd, sd_state, &crop); } else if (sel->target == V4L2_SEL_TGT_CROP && sel->pad == MSM_VFE_PAD_SRC) { struct v4l2_subdev_format fmt = { 0 }; - rect = __vfe_get_crop(line, cfg, sel->which); + rect = __vfe_get_crop(line, sd_state, sel->which); if (rect == NULL) return -EINVAL; - vfe_try_crop(line, cfg, &sel->r, sel->which); + vfe_try_crop(line, sd_state, &sel->r, sel->which); *rect = sel->r; /* Reset source pad format width and height */ fmt.which = sel->which; fmt.pad = MSM_VFE_PAD_SRC; - ret = vfe_get_format(sd, cfg, &fmt); + ret = vfe_get_format(sd, sd_state, &fmt); if (ret < 0) return ret; fmt.format.width = rect->width; fmt.format.height = rect->height; - ret = vfe_set_format(sd, cfg, &fmt); + ret = vfe_set_format(sd, sd_state, &fmt); } else { ret = -EINVAL; } @@ -1261,7 +1264,7 @@ static int vfe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } }; - return vfe_set_format(sd, fh ? fh->pad : NULL, &format); + return vfe_set_format(sd, fh ? fh->state : NULL, &format); } /* @@ -1301,8 +1304,7 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe, /* Memory */ - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res->reg[0]); - vfe->base = devm_ioremap_resource(dev, r); + vfe->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]); if (IS_ERR(vfe->base)) { dev_err(dev, "could not map memory\n"); return PTR_ERR(vfe->base); diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 54bac7ec14c5..91b15842c555 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -78,22 +78,32 @@ static const struct hfi_core_ops venus_core_ops = { .event_notify = venus_event_notify, }; +#define RPM_WAIT_FOR_IDLE_MAX_ATTEMPTS 10 + static void venus_sys_error_handler(struct work_struct *work) { struct venus_core *core = container_of(work, struct venus_core, work.work); - int ret = 0; - - pm_runtime_get_sync(core->dev); + int ret, i, max_attempts = RPM_WAIT_FOR_IDLE_MAX_ATTEMPTS; + const char *err_msg = ""; + bool failed = false; + + ret = pm_runtime_get_sync(core->dev); + if (ret < 0) { + err_msg = "resume runtime PM"; + max_attempts = 0; + failed = true; + } hfi_core_deinit(core, true); - dev_warn(core->dev, "system error has occurred, starting recovery!\n"); - mutex_lock(&core->lock); - while (pm_runtime_active(core->dev_dec) || pm_runtime_active(core->dev_enc)) + for (i = 0; i < max_attempts; i++) { + if (!pm_runtime_active(core->dev_dec) && !pm_runtime_active(core->dev_enc)) + break; msleep(10); + } venus_shutdown(core); @@ -101,31 +111,55 @@ static void venus_sys_error_handler(struct work_struct *work) pm_runtime_put_sync(core->dev); - while (core->pmdomains[0] && pm_runtime_active(core->pmdomains[0])) + for (i = 0; i < max_attempts; i++) { + if (!core->pmdomains[0] || !pm_runtime_active(core->pmdomains[0])) + break; usleep_range(1000, 1500); + } hfi_reinit(core); - pm_runtime_get_sync(core->dev); + ret = pm_runtime_get_sync(core->dev); + if (ret < 0) { + err_msg = "resume runtime PM"; + failed = true; + } - ret |= venus_boot(core); - ret |= hfi_core_resume(core, true); + ret = venus_boot(core); + if (ret && !failed) { + err_msg = "boot Venus"; + failed = true; + } + + ret = hfi_core_resume(core, true); + if (ret && !failed) { + err_msg = "resume HFI"; + failed = true; + } enable_irq(core->irq); mutex_unlock(&core->lock); - ret |= hfi_core_init(core); + ret = hfi_core_init(core); + if (ret && !failed) { + err_msg = "init HFI"; + failed = true; + } pm_runtime_put_sync(core->dev); - if (ret) { + if (failed) { disable_irq_nosync(core->irq); - dev_warn(core->dev, "recovery failed (%d)\n", ret); + dev_warn_ratelimited(core->dev, + "System error has occurred, recovery failed to %s\n", + err_msg); schedule_delayed_work(&core->work, msecs_to_jiffies(10)); return; } + dev_warn(core->dev, "system error has occurred (recovered)\n"); + mutex_lock(&core->lock); core->sys_error = false; mutex_unlock(&core->lock); diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 745f226a523f..8df2d497d706 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -155,7 +155,6 @@ struct venus_core { struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX]; struct icc_path *video_path; struct icc_path *cpucfg_path; - struct opp_table *opp_table; bool has_opp_table; struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX]; struct device_link *opp_dl_venus; @@ -293,6 +292,7 @@ struct clock_data { unsigned long freq; unsigned long vpp_freq; unsigned long vsp_freq; + unsigned long low_power_freq; }; #define to_venus_buffer(ptr) container_of(ptr, struct venus_buffer, vb) @@ -316,6 +316,10 @@ struct venus_ts_metadata { struct v4l2_timecode tc; }; +enum venus_inst_modes { + VENUS_LOW_POWER = BIT(0), +}; + /** * struct venus_inst - holds per instance parameters * @@ -445,6 +449,7 @@ struct venus_inst { unsigned int pic_struct; bool next_buf_last; bool drain_active; + enum venus_inst_modes flags; }; #define IS_V1(core) ((core)->res->hfi_version == HFI_VERSION_1XX) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index b813d6dba481..1fe6d463dc99 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -595,8 +595,7 @@ static int platform_get_bufreq(struct venus_inst *inst, u32 buftype, params.dec.is_secondary_output = inst->opb_buftype == HFI_BUFFER_OUTPUT2; params.dec.is_interlaced = - inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE ? - true : false; + inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE; } else { params.width = inst->out_width; params.height = inst->out_height; @@ -1627,6 +1626,8 @@ int venus_helper_session_init(struct venus_inst *inst) session_type); inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec, session_type); + inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(version, codec, + session_type); return 0; } diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index 11a8347e5f5c..f51024786991 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -3,6 +3,7 @@ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * Copyright (C) 2017 Linaro Ltd. */ +#include <linux/overflow.h> #include <linux/errno.h> #include <linux/hash.h> @@ -27,7 +28,7 @@ void pkt_sys_idle_indicator(struct hfi_sys_set_property_pkt *pkt, u32 enable) { struct hfi_enable *hfi = (struct hfi_enable *)&pkt->data[1]; - pkt->hdr.size = sizeof(*pkt) + sizeof(*hfi) + sizeof(u32); + pkt->hdr.size = struct_size(pkt, data, 1) + sizeof(*hfi); pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY; pkt->num_properties = 1; pkt->data[0] = HFI_PROPERTY_SYS_IDLE_INDICATOR; @@ -39,7 +40,7 @@ void pkt_sys_debug_config(struct hfi_sys_set_property_pkt *pkt, u32 mode, { struct hfi_debug_config *hfi; - pkt->hdr.size = sizeof(*pkt) + sizeof(*hfi) + sizeof(u32); + pkt->hdr.size = struct_size(pkt, data, 1) + sizeof(*hfi); pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY; pkt->num_properties = 1; pkt->data[0] = HFI_PROPERTY_SYS_DEBUG_CONFIG; @@ -50,7 +51,7 @@ void pkt_sys_debug_config(struct hfi_sys_set_property_pkt *pkt, u32 mode, void pkt_sys_coverage_config(struct hfi_sys_set_property_pkt *pkt, u32 mode) { - pkt->hdr.size = sizeof(*pkt) + sizeof(u32); + pkt->hdr.size = struct_size(pkt, data, 2); pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY; pkt->num_properties = 1; pkt->data[0] = HFI_PROPERTY_SYS_CONFIG_COVERAGE; @@ -116,7 +117,7 @@ void pkt_sys_power_control(struct hfi_sys_set_property_pkt *pkt, u32 enable) { struct hfi_enable *hfi = (struct hfi_enable *)&pkt->data[1]; - pkt->hdr.size = sizeof(*pkt) + sizeof(*hfi) + sizeof(u32); + pkt->hdr.size = struct_size(pkt, data, 1) + sizeof(*hfi); pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY; pkt->num_properties = 1; pkt->data[0] = HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL; @@ -1226,6 +1227,17 @@ pkt_session_set_property_4xx(struct hfi_session_set_property_pkt *pkt, pkt->shdr.hdr.size += sizeof(u32) + sizeof(*hdr10); break; } + case HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR: { + struct hfi_conceal_color_v4 *color = prop_data; + u32 *in = pdata; + + color->conceal_color_8bit = *in & 0xff; + color->conceal_color_8bit |= ((*in >> 10) & 0xff) << 8; + color->conceal_color_8bit |= ((*in >> 20) & 0xff) << 16; + color->conceal_color_10bit = *in; + pkt->shdr.hdr.size += sizeof(u32) + sizeof(*color); + break; + } case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE: case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: @@ -1279,17 +1291,6 @@ pkt_session_set_property_6xx(struct hfi_session_set_property_pkt *pkt, pkt->shdr.hdr.size += sizeof(u32) + sizeof(*cq); break; } - case HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR: { - struct hfi_conceal_color_v4 *color = prop_data; - u32 *in = pdata; - - color->conceal_color_8bit = *in & 0xff; - color->conceal_color_8bit |= ((*in >> 10) & 0xff) << 8; - color->conceal_color_8bit |= ((*in >> 20) & 0xff) << 16; - color->conceal_color_10bit = *in; - pkt->shdr.hdr.size += sizeof(u32) + sizeof(*color); - break; - } default: return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata); } diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.h b/drivers/media/platform/qcom/venus/hfi_cmds.h index 83705e237f1c..327ed90a2788 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.h +++ b/drivers/media/platform/qcom/venus/hfi_cmds.h @@ -68,7 +68,7 @@ struct hfi_sys_release_resource_pkt { struct hfi_sys_set_property_pkt { struct hfi_pkt_hdr hdr; u32 num_properties; - u32 data[1]; + u32 data[]; }; struct hfi_sys_get_property_pkt { diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index 63cd347a62da..b0a9beb4163c 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -415,9 +415,6 @@ #define HFI_BUFFER_MODE_RING 0x1000002 #define HFI_BUFFER_MODE_DYNAMIC 0x1000003 -#define HFI_VENC_PERFMODE_MAX_QUALITY 0x1 -#define HFI_VENC_PERFMODE_POWER_SAVE 0x2 - /* * HFI_PROPERTY_SYS_COMMON_START * HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x0000 @@ -848,6 +845,13 @@ struct hfi_framesize { u32 height; }; +#define HFI_VENC_PERFMODE_MAX_QUALITY 0x1 +#define HFI_VENC_PERFMODE_POWER_SAVE 0x2 + +struct hfi_perf_mode { + u32 video_perf_mode; +}; + #define VIDC_CORE_ID_DEFAULT 0 #define VIDC_CORE_ID_1 1 #define VIDC_CORE_ID_2 2 diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index a2d436d407b2..d9fde66f6fa8 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -251,11 +251,11 @@ sys_get_prop_image_version(struct device *dev, req_bytes = pkt->hdr.size - sizeof(*pkt); - if (req_bytes < VER_STR_SZ || !pkt->data[1] || pkt->num_properties > 1) + if (req_bytes < VER_STR_SZ || !pkt->data[0] || pkt->num_properties > 1) /* bad packet */ return; - img_ver = (u8 *)&pkt->data[1]; + img_ver = pkt->data; dev_dbg(dev, VDBGL "F/W version: %s\n", img_ver); @@ -277,7 +277,7 @@ static void hfi_sys_property_info(struct venus_core *core, return; } - switch (pkt->data[0]) { + switch (pkt->property) { case HFI_PROPERTY_SYS_IMAGE_VERSION: sys_get_prop_image_version(dev, pkt); break; @@ -338,7 +338,7 @@ session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt, /* bad packet */ return HFI_ERR_SESSION_INVALID_PARAMETER; - hfi = (struct hfi_profile_level *)&pkt->data[1]; + hfi = (struct hfi_profile_level *)&pkt->data[0]; profile_level->profile = hfi->profile; profile_level->level = hfi->level; @@ -355,11 +355,11 @@ session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt, req_bytes = pkt->shdr.hdr.size - sizeof(*pkt); - if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[1]) + if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[0]) /* bad packet */ return HFI_ERR_SESSION_INVALID_PARAMETER; - buf_req = (struct hfi_buffer_requirements *)&pkt->data[1]; + buf_req = (struct hfi_buffer_requirements *)&pkt->data[0]; if (!buf_req) return HFI_ERR_SESSION_INVALID_PARAMETER; @@ -391,7 +391,7 @@ static void hfi_session_prop_info(struct venus_core *core, goto done; } - switch (pkt->data[0]) { + switch (pkt->property) { case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: memset(hprop->bufreq, 0, sizeof(hprop->bufreq)); error = session_get_prop_buf_req(pkt, hprop->bufreq); @@ -404,7 +404,7 @@ static void hfi_session_prop_info(struct venus_core *core, case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: break; default: - dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->data[0]); + dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->property); return; } diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.h b/drivers/media/platform/qcom/venus/hfi_msgs.h index 526d9f5b487b..510513697335 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.h +++ b/drivers/media/platform/qcom/venus/hfi_msgs.h @@ -113,7 +113,8 @@ struct hfi_msg_sys_ping_ack_pkt { struct hfi_msg_sys_property_info_pkt { struct hfi_pkt_hdr hdr; u32 num_properties; - u32 data[1]; + u32 property; + u8 data[]; }; struct hfi_msg_session_load_resources_done_pkt { @@ -233,7 +234,8 @@ struct hfi_msg_session_parse_sequence_header_done_pkt { struct hfi_msg_session_property_info_pkt { struct hfi_session_hdr_pkt shdr; u32 num_properties; - u32 data[1]; + u32 property; + u8 data[]; }; struct hfi_msg_session_release_resources_done_pkt { diff --git a/drivers/media/platform/qcom/venus/hfi_platform.c b/drivers/media/platform/qcom/venus/hfi_platform.c index 8f47804e973f..f5b4e1f4764f 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform.c +++ b/drivers/media/platform/qcom/venus/hfi_platform.c @@ -50,6 +50,22 @@ hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, u32 session return freq; } +unsigned long +hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, u32 session_type) +{ + const struct hfi_platform *plat; + unsigned long freq = 0; + + plat = hfi_platform_get(version); + if (!plat) + return 0; + + if (plat->codec_lp_freq) + freq = plat->codec_lp_freq(session_type, codec); + + return freq; +} + u8 hfi_platform_num_vpp_pipes(enum hfi_version version) { const struct hfi_platform *plat; diff --git a/drivers/media/platform/qcom/venus/hfi_platform.h b/drivers/media/platform/qcom/venus/hfi_platform.h index 3819bb2b36bd..2dbe608c53af 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform.h +++ b/drivers/media/platform/qcom/venus/hfi_platform.h @@ -43,11 +43,13 @@ struct hfi_platform_codec_freq_data { u32 session_type; unsigned long vpp_freq; unsigned long vsp_freq; + unsigned long low_power_freq; }; struct hfi_platform { unsigned long (*codec_vpp_freq)(u32 session_type, u32 codec); unsigned long (*codec_vsp_freq)(u32 session_type, u32 codec); + unsigned long (*codec_lp_freq)(u32 session_type, u32 codec); void (*codecs)(u32 *enc_codecs, u32 *dec_codecs, u32 *count); const struct hfi_plat_caps *(*capabilities)(unsigned int *entries); u8 (*num_vpp_pipes)(void); @@ -63,5 +65,7 @@ unsigned long hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 code u32 session_type); unsigned long hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, u32 session_type); +unsigned long hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, + u32 session_type); u8 hfi_platform_num_vpp_pipes(enum hfi_version version); #endif diff --git a/drivers/media/platform/qcom/venus/hfi_platform_v4.c b/drivers/media/platform/qcom/venus/hfi_platform_v4.c index 3848bb6d7408..3f7f5277a50e 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform_v4.c +++ b/drivers/media/platform/qcom/venus/hfi_platform_v4.c @@ -262,14 +262,14 @@ static void get_codecs(u32 *enc_codecs, u32 *dec_codecs, u32 *count) } static const struct hfi_platform_codec_freq_data codec_freq_data[] = { - { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 10 }, - { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 10 }, - { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 10 }, - { V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 10 }, - { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 10 }, - { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 10 }, - { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 10 }, - { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 10 }, + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 10, 320 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 10, 320 }, + { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 10, 320 }, + { V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 10, 200 }, + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 10, 200 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 10, 200 }, + { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 10, 200 }, + { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 10, 200 }, }; static const struct hfi_platform_codec_freq_data * @@ -311,9 +311,21 @@ static unsigned long codec_vsp_freq(u32 session_type, u32 codec) return 0; } +static unsigned long codec_lp_freq(u32 session_type, u32 codec) +{ + const struct hfi_platform_codec_freq_data *data; + + data = get_codec_freq_data(session_type, codec); + if (data) + return data->low_power_freq; + + return 0; +} + const struct hfi_platform hfi_plat_v4 = { .codec_vpp_freq = codec_vpp_freq, .codec_vsp_freq = codec_vsp_freq, + .codec_lp_freq = codec_lp_freq, .codecs = get_codecs, .capabilities = get_capabilities, }; diff --git a/drivers/media/platform/qcom/venus/hfi_platform_v6.c b/drivers/media/platform/qcom/venus/hfi_platform_v6.c index dd1a03911b6c..d8243b22568a 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform_v6.c +++ b/drivers/media/platform/qcom/venus/hfi_platform_v6.c @@ -262,14 +262,14 @@ static void get_codecs(u32 *enc_codecs, u32 *dec_codecs, u32 *count) } static const struct hfi_platform_codec_freq_data codec_freq_data[] = { - { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 25 }, - { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 25 }, - { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 60 }, - { V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 25 }, - { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 25 }, - { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 25 }, - { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 60 }, - { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 60 }, + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 25, 320 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 25, 320 }, + { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 60, 320 }, + { V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 25, 200 }, + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 25, 200 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 25, 200 }, + { V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 60, 200 }, + { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 60, 200 }, }; static const struct hfi_platform_codec_freq_data * @@ -311,6 +311,17 @@ static unsigned long codec_vsp_freq(u32 session_type, u32 codec) return 0; } +static unsigned long codec_lp_freq(u32 session_type, u32 codec) +{ + const struct hfi_platform_codec_freq_data *data; + + data = get_codec_freq_data(session_type, codec); + if (data) + return data->low_power_freq; + + return 0; +} + static u8 num_vpp_pipes(void) { return 4; @@ -319,6 +330,7 @@ static u8 num_vpp_pipes(void) const struct hfi_platform hfi_plat_v6 = { .codec_vpp_freq = codec_vpp_freq, .codec_vsp_freq = codec_vsp_freq, + .codec_lp_freq = codec_lp_freq, .codecs = get_codecs, .capabilities = get_capabilities, .num_vpp_pipes = num_vpp_pipes, diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index c7e1ebec47ee..3e2345eb47f7 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -300,16 +300,15 @@ static int core_get_v1(struct venus_core *core) if (ret) return ret; - core->opp_table = dev_pm_opp_set_clkname(core->dev, "core"); - if (IS_ERR(core->opp_table)) - return PTR_ERR(core->opp_table); + ret = devm_pm_opp_set_clkname(core->dev, "core"); + if (ret) + return ret; return 0; } static void core_put_v1(struct venus_core *core) { - dev_pm_opp_put_clkname(core->opp_table); } static int core_power_v1(struct venus_core *core, int on) @@ -524,8 +523,50 @@ static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask) return 0; } +static inline int power_save_mode_enable(struct venus_inst *inst, + bool enable) +{ + struct venc_controls *enc_ctr = &inst->controls.enc; + const u32 ptype = HFI_PROPERTY_CONFIG_VENC_PERF_MODE; + u32 venc_mode; + int ret = 0; + + if (inst->session_type != VIDC_SESSION_TYPE_ENC) + return 0; + + if (enc_ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) + enable = false; + + venc_mode = enable ? HFI_VENC_PERFMODE_POWER_SAVE : + HFI_VENC_PERFMODE_MAX_QUALITY; + + ret = hfi_session_set_property(inst, ptype, &venc_mode); + if (ret) + return ret; + + inst->flags = enable ? inst->flags | VENUS_LOW_POWER : + inst->flags & ~VENUS_LOW_POWER; + + return ret; +} + +static int move_core_to_power_save_mode(struct venus_core *core, + u32 core_id) +{ + struct venus_inst *inst = NULL; + + mutex_lock(&core->lock); + list_for_each_entry(inst, &core->instances, list) { + if (inst->clk_data.core_id == core_id && + inst->session_type == VIDC_SESSION_TYPE_ENC) + power_save_mode_enable(inst, true); + } + mutex_unlock(&core->lock); + return 0; +} + static void -min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load) +min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load, bool low_power) { u32 mbs_per_sec, load, core1_load = 0, core2_load = 0; u32 cores_max = core_num_max(inst); @@ -543,7 +584,14 @@ min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load) if (inst_pos->state != INST_START) continue; - vpp_freq = inst_pos->clk_data.vpp_freq; + if (inst->session_type == VIDC_SESSION_TYPE_DEC) + vpp_freq = inst_pos->clk_data.vpp_freq; + else if (inst->session_type == VIDC_SESSION_TYPE_ENC) + vpp_freq = low_power ? inst_pos->clk_data.vpp_freq : + inst_pos->clk_data.low_power_freq; + else + continue; + coreid = inst_pos->clk_data.core_id; mbs_per_sec = load_per_instance(inst_pos); @@ -575,9 +623,11 @@ static int decide_core(struct venus_inst *inst) { const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE; struct venus_core *core = inst->core; - u32 min_coreid, min_load, inst_load; + u32 min_coreid, min_load, cur_inst_load; + u32 min_lp_coreid, min_lp_load, cur_inst_lp_load; struct hfi_videocores_usage_type cu; unsigned long max_freq; + int ret = 0; if (legacy_binding) { if (inst->session_type == VIDC_SESSION_TYPE_DEC) @@ -591,23 +641,43 @@ static int decide_core(struct venus_inst *inst) if (inst->clk_data.core_id != VIDC_CORE_ID_DEFAULT) return 0; - inst_load = load_per_instance(inst); - inst_load *= inst->clk_data.vpp_freq; - max_freq = core->res->freq_tbl[0].freq; + cur_inst_load = load_per_instance(inst); + cur_inst_load *= inst->clk_data.vpp_freq; + /*TODO : divide this inst->load by work_route */ - min_loaded_core(inst, &min_coreid, &min_load); + cur_inst_lp_load = load_per_instance(inst); + cur_inst_lp_load *= inst->clk_data.low_power_freq; + /*TODO : divide this inst->load by work_route */ - if ((inst_load + min_load) > max_freq) { - dev_warn(core->dev, "HW is overloaded, needed: %u max: %lu\n", - inst_load, max_freq); + max_freq = core->res->freq_tbl[0].freq; + + min_loaded_core(inst, &min_coreid, &min_load, false); + min_loaded_core(inst, &min_lp_coreid, &min_lp_load, true); + + if (cur_inst_load + min_load <= max_freq) { + inst->clk_data.core_id = min_coreid; + cu.video_core_enable_mask = min_coreid; + } else if (cur_inst_lp_load + min_load <= max_freq) { + /* Move current instance to LP and return */ + inst->clk_data.core_id = min_coreid; + cu.video_core_enable_mask = min_coreid; + power_save_mode_enable(inst, true); + } else if (cur_inst_lp_load + min_lp_load <= max_freq) { + /* Move all instances to LP mode and return */ + inst->clk_data.core_id = min_lp_coreid; + cu.video_core_enable_mask = min_lp_coreid; + move_core_to_power_save_mode(core, min_lp_coreid); + } else { + dev_warn(core->dev, "HW can't support this load"); return -EINVAL; } - inst->clk_data.core_id = min_coreid; - cu.video_core_enable_mask = min_coreid; - done: - return hfi_session_set_property(inst, ptype, &cu); + ret = hfi_session_set_property(inst, ptype, &cu); + if (ret) + return ret; + + return ret; } static int acquire_core(struct venus_inst *inst) @@ -788,7 +858,6 @@ static int venc_power_v4(struct device *dev, int on) static int vcodec_domains_get(struct venus_core *core) { int ret; - struct opp_table *opp_table; struct device **opp_virt_dev; struct device *dev = core->dev; const struct venus_resources *res = core->res; @@ -811,11 +880,9 @@ skip_pmdomains: return 0; /* Attach the power domain for setting performance state */ - opp_table = dev_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev); - if (IS_ERR(opp_table)) { - ret = PTR_ERR(opp_table); + ret = devm_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev); + if (ret) goto opp_attach_err; - } core->opp_pmdomain = *opp_virt_dev; core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain, @@ -824,13 +891,11 @@ skip_pmdomains: DL_FLAG_STATELESS); if (!core->opp_dl_venus) { ret = -ENODEV; - goto opp_dl_add_err; + goto opp_attach_err; } return 0; -opp_dl_add_err: - dev_pm_opp_detach_genpd(core->opp_table); opp_attach_err: for (i = 0; i < res->vcodec_pmdomains_num; i++) { if (IS_ERR_OR_NULL(core->pmdomains[i])) @@ -861,8 +926,6 @@ skip_pmdomains: if (core->opp_dl_venus) device_link_del(core->opp_dl_venus); - - dev_pm_opp_detach_genpd(core->opp_table); } static int core_resets_reset(struct venus_core *core) @@ -941,45 +1004,33 @@ static int core_get_v4(struct venus_core *core) if (legacy_binding) return 0; - core->opp_table = dev_pm_opp_set_clkname(dev, "core"); - if (IS_ERR(core->opp_table)) - return PTR_ERR(core->opp_table); + ret = devm_pm_opp_set_clkname(dev, "core"); + if (ret) + return ret; if (core->res->opp_pmdomain) { - ret = dev_pm_opp_of_add_table(dev); + ret = devm_pm_opp_of_add_table(dev); if (!ret) { core->has_opp_table = true; } else if (ret != -ENODEV) { dev_err(dev, "invalid OPP table in device tree\n"); - dev_pm_opp_put_clkname(core->opp_table); return ret; } } ret = vcodec_domains_get(core); - if (ret) { - if (core->has_opp_table) - dev_pm_opp_of_remove_table(dev); - dev_pm_opp_put_clkname(core->opp_table); + if (ret) return ret; - } return 0; } static void core_put_v4(struct venus_core *core) { - struct device *dev = core->dev; - if (legacy_binding) return; vcodec_domains_put(core); - - if (core->has_opp_table) - dev_pm_opp_of_remove_table(dev); - dev_pm_opp_put_clkname(core->opp_table); - } static int core_power_v4(struct venus_core *core, int on) @@ -990,9 +1041,8 @@ static int core_power_v4(struct venus_core *core, int on) if (on == POWER_ON) { if (pmctrl) { - ret = pm_runtime_get_sync(pmctrl); + ret = pm_runtime_resume_and_get(pmctrl); if (ret < 0) { - pm_runtime_put_noidle(pmctrl); return ret; } } @@ -1026,7 +1076,7 @@ static int core_power_v4(struct venus_core *core, int on) static unsigned long calculate_inst_freq(struct venus_inst *inst, unsigned long filled_len) { - unsigned long vpp_freq = 0, vsp_freq = 0; + unsigned long vpp_freq_per_mb = 0, vpp_freq = 0, vsp_freq = 0; u32 fps = (u32)inst->fps; u32 mbs_per_sec; @@ -1035,7 +1085,12 @@ static unsigned long calculate_inst_freq(struct venus_inst *inst, if (inst->state != INST_START) return 0; - vpp_freq = mbs_per_sec * inst->clk_data.vpp_freq; + if (inst->session_type == VIDC_SESSION_TYPE_ENC) + vpp_freq_per_mb = inst->flags & VENUS_LOW_POWER ? + inst->clk_data.low_power_freq : + inst->clk_data.vpp_freq; + + vpp_freq = mbs_per_sec * vpp_freq_per_mb; /* 21 / 20 is overhead factor */ vpp_freq += vpp_freq / 20; vsp_freq = mbs_per_sec * inst->clk_data.vsp_freq; diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index ddb7cd39424e..198e47eb63f4 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -568,10 +568,10 @@ static int vdec_pm_get(struct venus_inst *inst) int ret; mutex_lock(&core->pm_lock); - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); mutex_unlock(&core->pm_lock); - return ret < 0 ? ret : 0; + return ret; } static int vdec_pm_put(struct venus_inst *inst, bool autosuspend) @@ -601,7 +601,7 @@ static int vdec_pm_get_put(struct venus_inst *inst) mutex_lock(&core->pm_lock); if (pm_runtime_suspended(dev)) { - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) goto error; diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 4a7291f934b6..8dd49d4f124c 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -1205,9 +1205,9 @@ static int venc_open(struct file *file) venus_helper_init_instance(inst); - ret = pm_runtime_get_sync(core->dev_enc); + ret = pm_runtime_resume_and_get(core->dev_enc); if (ret < 0) - goto err_put_sync; + goto err_free; ret = venc_ctrl_init(inst); if (ret) @@ -1252,6 +1252,7 @@ err_ctrl_deinit: venc_ctrl_deinit(inst); err_put_sync: pm_runtime_put_sync(core->dev_enc); +err_free: kfree(inst); return ret; } |