static int flite_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { struct flite_dev *flite = to_flite_dev(sd); struct flite_fmt const *f_fmt = find_flite_format(mf); struct flite_frame *f_frame = &flite->source_frame; flite_dbg("w: %d, h: %d", mf->width, mf->height); if (unlikely(!f_fmt)) { flite_err("f_fmt is null"); return -EINVAL; } flite->mbus_fmt = *mf; /* * These are the datas from fimc * If you want to crop the image, you can use s_crop */ f_frame->o_width = mf->width; f_frame->o_height = mf->height; f_frame->width = mf->width; f_frame->height = mf->height; f_frame->offs_h = 0; f_frame->offs_v = 0; return 0; }
static int flite_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { struct flite_dev *flite = to_flite_dev(sd); mf = &flite->mbus_fmt; return 0; }
static int flite_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop) { struct flite_dev *flite = to_flite_dev(sd); struct flite_frame *f; f = &flite->source_frame; crop->c.left = f->offs_h; crop->c.top = f->offs_v; crop->c.width = f->width; crop->c.height = f->height; return 0; }
static int flite_s_stream(struct v4l2_subdev *sd, int enable) { struct flite_dev *flite = to_flite_dev(sd); u32 index = flite->pdata->active_cam_index; struct s3c_platform_camera *cam = flite->pdata->cam[index]; u32 int_src = FLITE_REG_CIGCTRL_IRQ_LASTEN0_ENABLE; unsigned long flags; int ret = 0; if (enable) flite_hw_reset(flite); spin_lock_irqsave(&flite->slock, flags); if (test_bit(FLITE_ST_SUSPENDED, &flite->state)) goto s_stream_unlock; if (enable) { flite_hw_set_cam_channel(flite); flite_hw_set_cam_source_size(flite); flite_hw_set_camera_type(flite, cam); ret = flite_hw_set_source_format(flite); if (unlikely(ret < 0)) goto s_stream_unlock; if (cam->use_isp) flite_hw_set_output_dma(flite, false); flite_hw_set_interrupt_source(flite, int_src); flite_hw_set_config_irq(flite, cam); flite_hw_set_window_offset(flite); flite_hw_set_capture_start(flite); set_bit(FLITE_ST_STREAMING, &flite->state); } else { if (test_bit(FLITE_ST_STREAMING, &flite->state)) { flite_hw_set_capture_stop(flite); spin_unlock_irqrestore(&flite->slock, flags); ret = wait_event_timeout(flite->irq_queue, !test_bit(FLITE_ST_STREAMING, &flite->state), HZ/20); /* 50 ms */ if (unlikely(!ret)) { v4l2_err(sd, "wait timeout\n"); ret = -EBUSY; } } return ret; } s_stream_unlock: spin_unlock_irqrestore(&flite->slock, flags); return ret; }
static int flite_remove(struct platform_device *pdev) { struct v4l2_subdev *sd = platform_get_drvdata(pdev); struct flite_dev *flite = to_flite_dev(sd); struct resource *res = flite->regs_res; flite_s_power(&flite->sd, 0); pm_runtime_disable(&pdev->dev); free_irq(flite->irq, flite); iounmap(flite->regs); release_mem_region(res->start, resource_size(res)); kfree(flite); return 0; }
static int flite_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct v4l2_subdev *sd = platform_get_drvdata(pdev); struct flite_dev *flite = to_flite_dev(sd); unsigned long flags; spin_lock_irqsave(&flite->slock, flags); clear_bit(FLITE_ST_SUSPENDED, &flite->state); spin_unlock_irqrestore(&flite->slock, flags); return 0; }
static int flite_s_power(struct v4l2_subdev *sd, int on) { struct flite_dev *flite = to_flite_dev(sd); int ret = 0; if (on) { pm_runtime_get_sync(&flite->pdev->dev); set_bit(FLITE_ST_POWERED, &flite->state); } else { pm_runtime_put_sync(&flite->pdev->dev); clear_bit(FLITE_ST_POWERED, &flite->state); } return ret; }
static int flite_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cc) { struct flite_dev *flite = to_flite_dev(sd); struct flite_frame *f; f = &flite->source_frame; cc->bounds.left = 0; cc->bounds.top = 0; cc->bounds.width = f->o_width; cc->bounds.height = f->o_height; cc->defrect = cc->bounds; return 0; }
static int flite_subdev_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_crop *crop) { struct flite_dev *flite = to_flite_dev(sd); struct v4l2_rect fcrop; fcrop.left = fcrop.top = fcrop.width = fcrop.height = 0; if (crop->pad != FLITE_PAD_SINK) return -EINVAL; __flite_get_crop(flite, fh, crop->pad, crop->which, &fcrop); crop->rect = fcrop; return 0; }
static int flite_subdev_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) { struct flite_dev *flite = to_flite_dev(sd); struct v4l2_mbus_framefmt *mf; if (fmt->pad != FLITE_PAD_SINK) return -EPERM; mf = __flite_get_format(flite, fh, fmt->pad, fmt->which); if (mf == NULL) return -EINVAL; flite_try_format(flite, fh, &fmt->format, fmt->which); *mf = fmt->format; return 0; }
static int flite_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct v4l2_subdev *sd = platform_get_drvdata(pdev); struct flite_dev *flite = to_flite_dev(sd); unsigned long flags; spin_lock_irqsave(&flite->slock, flags); if (test_bit(FLITE_ST_POWERED, &flite->state)) flite_s_power(sd, true); if (test_bit(FLITE_ST_STREAMING, &flite->state)) flite_s_stream(sd, true); clear_bit(FLITE_ST_SUSPENDED, &flite->state); spin_unlock_irqrestore(&flite->slock, flags); return 0; }
static int flite_subdev_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_crop *crop) { struct flite_dev *flite = to_flite_dev(sd); struct flite_frame *f_frame = &flite->source_frame; if (crop->pad != FLITE_PAD_SINK) return -EINVAL; flite_try_crop(flite, &crop->rect); if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { f_frame->offs_h = crop->rect.left; f_frame->offs_v = crop->rect.top; f_frame->width = crop->rect.width; f_frame->height = crop->rect.height; } return 0; }
static int flite_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) { struct flite_dev *flite = to_flite_dev(sd); struct v4l2_mbus_framefmt *mf; mf = __flite_get_format(flite, fh, fmt->pad, fmt->which); if (mf == NULL) return -EINVAL; fmt->format = *mf; if (fmt->pad != FLITE_PAD_SINK) { struct flite_frame *f = &flite->source_frame; fmt->format.width = f->width; fmt->format.height = f->height; } return 0; }
static int flite_link_setup(struct media_entity *entity, const struct media_pad *local, const struct media_pad *remote, u32 flags) { struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); struct flite_dev *flite = to_flite_dev(sd); flite_info(""); switch (local->index | media_entity_type(remote->entity)) { case FLITE_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: if (flags & MEDIA_LNK_FL_ENABLED) { if (flite->input != FLITE_INPUT_NONE) { flite_err("link is busy"); return -EBUSY; } if (remote->index == CSIS_PAD_SOURCE) flite->input |= FLITE_INPUT_CSIS; else flite->input |= FLITE_INPUT_SENSOR; } else { flite->input = FLITE_INPUT_NONE; } break; case FLITE_PAD_SOURCE_PREVIEW | MEDIA_ENT_T_V4L2_SUBDEV: /* fall through */ case FLITE_PAD_SOURCE_CAMCORDING | MEDIA_ENT_T_V4L2_SUBDEV: if (flags & MEDIA_LNK_FL_ENABLED) flite->output = FLITE_OUTPUT_GSC; else flite->output = FLITE_OUTPUT_NONE; break; default: flite_err("ERR link"); return -EINVAL; } return 0; }
static int flite_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop) { struct flite_dev *flite = to_flite_dev(sd); struct flite_frame *f; f = &flite->source_frame; if (crop->c.left + crop->c.width > f->o_width) return -EINVAL; if (crop->c.top + crop->c.height > f->o_height) return -EINVAL; f->width = crop->c.width; f->height = crop->c.height; f->offs_h = crop->c.left; f->offs_v = crop->c.top; flite_dbg("width : %d, height : %d, offs_h : %d, off_v : %dn", f->width, f->height, f->offs_h, f->offs_v); return 0; }