static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect, struct v4l2_format *f, bool ceu_can_scale) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct sh_mobile_ceu_cam *cam = icd->host_priv; struct device *dev = icd->dev.parent; struct v4l2_format f_tmp = *f; struct v4l2_pix_format *pix_tmp = &f_tmp.fmt.pix; unsigned int scale_h, scale_v; int ret; ret = client_s_fmt(icd, &f_tmp, ceu_can_scale); if (ret < 0) return ret; dev_geo(dev, "5: camera scaled to %ux%u\n", pix_tmp->width, pix_tmp->height); ret = get_camera_scales(sd, rect, &scale_h, &scale_v); if (ret < 0) return ret; dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v); cam->cam_width = pix_tmp->width; cam->cam_height = pix_tmp->height; f->fmt.pix.width = pix_tmp->width; f->fmt.pix.height = pix_tmp->height; ceu_rect->left = scale_down(sub_rect->left, scale_h); ceu_rect->width = scale_down(sub_rect->width, scale_h); ceu_rect->top = scale_down(sub_rect->top, scale_v); ceu_rect->height = scale_down(sub_rect->height, scale_v); dev_geo(dev, "8: new CEU rect %ux%u@%u:%u\n", ceu_rect->width, ceu_rect->height, ceu_rect->left, ceu_rect->top); return 0; }
void nvhost_scale3d_set_throughput_hint(int hint) { if (!scale3d.enable) return; if (!scale3d.p_use_throughput_hint) return; scale3d.last_throughput_hint = ktime_get(); if (scale3d.p_use_throughput_hint) { if (hint >= scale3d.p_throughput_hi_limit) scale_down(); else if (hint <= scale3d.p_throughput_lo_limit) scale_up(); } }
static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_format cam_f = *f; struct v4l2_pix_format *cam_pix = &cam_f.fmt.pix; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; struct v4l2_crop cam_crop; struct v4l2_rect *cam_rect = &cam_crop.c, cam_subrect, ceu_rect; unsigned int scale_cam_h, scale_cam_v; u16 scale_v, scale_h; int ret; bool is_interlaced, image_mode; switch (pix->field) { case V4L2_FIELD_INTERLACED: is_interlaced = true; break; case V4L2_FIELD_ANY: default: pix->field = V4L2_FIELD_NONE; case V4L2_FIELD_NONE: is_interlaced = false; break; } xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { dev_warn(dev, "Format %x not found\n", pixfmt); return -EINVAL; } cam_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = client_g_rect(sd, cam_rect); if (ret < 0) return ret; ret = get_camera_scales(sd, cam_rect, &scale_cam_h, &scale_cam_v); if (ret < 0) return ret; dev_geo(dev, "1: camera scales %u:%u\n", scale_cam_h, scale_cam_v); ret = get_camera_subwin(icd, &cam_subrect, scale_cam_h, scale_cam_v); if (ret < 0) return ret; dev_geo(dev, "2: subwin %ux%u@%u:%u\n", cam_subrect.width, cam_subrect.height, cam_subrect.left, cam_subrect.top); scale_h = calc_generic_scale(cam_subrect.width, pix->width); scale_v = calc_generic_scale(cam_subrect.height, pix->height); dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); cam_pix->width = scale_down(cam_rect->width, scale_h); cam_pix->height = scale_down(cam_rect->height, scale_v); cam_pix->pixelformat = xlate->cam_fmt->fourcc; switch (pixfmt) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: image_mode = true; break; default: image_mode = false; } dev_geo(dev, "4: camera output %ux%u\n", cam_pix->width, cam_pix->height); ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &cam_f, image_mode && !is_interlaced); dev_geo(dev, "5-9: client scale %d\n", ret); dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", ret, cam_pix->width, cam_pix->height, pix->width, pix->height); if (ret < 0) return ret; if (pix->width > cam_pix->width) pix->width = cam_pix->width; if (pix->width > ceu_rect.width) pix->width = ceu_rect.width; if (pix->height > cam_pix->height) pix->height = cam_pix->height; if (pix->height > ceu_rect.height) pix->height = ceu_rect.height; scale_h = calc_scale(ceu_rect.width, &pix->width); scale_v = calc_scale(ceu_rect.height, &pix->height); dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", ceu_rect.width, scale_h, pix->width, ceu_rect.height, scale_v, pix->height); pcdev->cflcr = scale_h | (scale_v << 16); icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; cam->camera_fmt = xlate->cam_fmt; cam->ceu_rect = ceu_rect; pcdev->is_interlaced = is_interlaced; pcdev->image_mode = image_mode; return 0; }
static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, struct v4l2_crop *a) { struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; struct v4l2_crop cam_crop; struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; struct v4l2_format f; struct v4l2_pix_format *pix = &f.fmt.pix; unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v, out_width, out_height; u32 capsr, cflcr; int ret; ret = get_scales(icd, &scale_comb_h, &scale_comb_v); if (ret < 0) return ret; dev_geo(dev, "1: combined scales %u:%u\n", scale_comb_h, scale_comb_v); ret = client_s_crop(sd, a, &cam_crop); if (ret < 0) return ret; dev_geo(dev, "2: camera cropped to %ux%u@%u:%u\n", cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); out_width = scale_down(rect->width, scale_comb_h); out_height = scale_down(rect->height, scale_comb_v); if (out_width > 2560) out_width = 2560; else if (out_width < 2) out_width = 2; if (out_height > 1920) out_height = 1920; else if (out_height < 4) out_height = 4; dev_geo(dev, "3: Adjusted output %ux%u\n", out_width, out_height); pix->width = scale_down(cam_rect->width, scale_comb_h); pix->height = scale_down(cam_rect->height, scale_comb_v); dev_geo(dev, "5: camera target %ux%u\n", pix->width, pix->height); pix->pixelformat = cam->camera_fmt->fourcc; pix->colorspace = cam->camera_fmt->colorspace; capsr = capture_save_reset(pcdev); dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); rect->left -= cam_rect->left; rect->top -= cam_rect->top; f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = client_scale(icd, cam_rect, rect, ceu_rect, &f, pcdev->image_mode && !pcdev->is_interlaced); dev_geo(dev, "6-9: %d\n", ret); sh_mobile_ceu_set_rect(icd, out_width, out_height); dev_geo(dev, "10: CEU cropped to %ux%u@%u:%u\n", ceu_rect->width, ceu_rect->height, ceu_rect->left, ceu_rect->top); scale_ceu_h = calc_scale(ceu_rect->width, &out_width); scale_ceu_v = calc_scale(ceu_rect->height, &out_height); dev_geo(dev, "11: CEU scales %u:%u\n", scale_ceu_h, scale_ceu_v); cflcr = scale_ceu_h | (scale_ceu_v << 16); if (cflcr != pcdev->cflcr) { pcdev->cflcr = cflcr; ceu_write(pcdev, CFLCR, cflcr); } if (pcdev->active) capsr |= 1; capture_restore(pcdev, capsr); icd->user_width = out_width; icd->user_height = out_height; return ret; }