static int gsc_cap_config_camclk(struct gsc_dev *gsc, struct exynos_isp_info *isp_info, int i) { struct gsc_capture_device *gsc_cap = &gsc->cap; struct clk *camclk; struct clk *srclk; camclk = clk_get(&gsc->pdev->dev, isp_info->cam_clk_name); if (IS_ERR_OR_NULL(camclk)) { gsc_err("failed to get cam clk"); return -ENXIO; } gsc_cap->sensor[i].camclk = camclk; srclk = clk_get(&gsc->pdev->dev, isp_info->cam_srclk_name); if (IS_ERR_OR_NULL(srclk)) { clk_put(camclk); gsc_err("failed to get cam source clk\n"); return -ENXIO; } clk_set_parent(camclk, srclk); clk_set_rate(camclk, isp_info->clk_frequency); clk_put(srclk); return 0; }
void gsc_op_timer_handler(unsigned long arg) { struct gsc_dev *gsc = (struct gsc_dev *)arg; struct gsc_ctx *ctx = v4l2_m2m_get_curr_priv(gsc->m2m.m2m_dev); struct vb2_buffer *src_vb, *dst_vb; if (!test_bit(ST_M2M_RUN, &gsc->state)) { gsc_warn("gsc state is 0x%lx", gsc->state); return; } gsc_dump_registers(gsc); clear_bit(ST_M2M_RUN, &gsc->state); pm_runtime_put(&gsc->pdev->dev); src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); if (src_vb && dst_vb) { v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR); v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR); } gsc_err("GSCALER[%d] interrupt hasn't been triggered", gsc->id); gsc_err("erro ctx: %p, ctx->state: 0x%x", ctx, ctx->state); }
void gsc_op_timer_handler(unsigned long arg) { struct gsc_dev *gsc = (struct gsc_dev *)arg; struct gsc_ctx *ctx = v4l2_m2m_get_curr_priv(gsc->m2m.m2m_dev); struct vb2_buffer *src_vb, *dst_vb; #ifdef GSC_PERF gsc->end_time = sched_clock(); gsc_err("expire time: %llu\n", gsc->end_time - gsc->start_time); #endif gsc_dump_registers(gsc); exynos_iommu_dump_status(&gsc->pdev->dev); clear_bit(ST_M2M_RUN, &gsc->state); pm_runtime_put(&gsc->pdev->dev); gsc->runtime_put_cnt++; src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); if (src_vb && dst_vb) { v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR); v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR); } gsc_err("GSCALER[%d] interrupt hasn't been triggered", gsc->id); gsc_err("erro ctx: %p, ctx->state: 0x%x", ctx, ctx->state); }
int gsc_fill_addr(struct gsc_ctx *ctx) { struct gsc_frame *s_frame, *d_frame; struct vb2_buffer *vb = NULL; int ret = 0; s_frame = &ctx->s_frame; d_frame = &ctx->d_frame; vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); if (vb->num_planes != s_frame->fmt->num_planes) { gsc_err(" vb(%p) planes=%d s_frame(%p) planes=%d\n", vb, vb->num_planes, s_frame, s_frame->fmt->num_planes); return -EINVAL; } ret = gsc_prepare_addr(ctx, vb, s_frame, &s_frame->addr); if (ret) return ret; vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); if (vb->num_planes != d_frame->fmt->num_planes) { gsc_err("vb(%p) planes=%d d_frame(%p) planes=%d\n", vb, vb->num_planes, d_frame, d_frame->fmt->num_planes); return -EINVAL; } ret = gsc_prepare_addr(ctx, vb, d_frame, &d_frame->addr); return ret; }
static int gsc_capture_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct gsc_dev *gsc = video_drvdata(file); struct gsc_pipeline *p = &gsc->pipeline; int ret; if (gsc_cap_active(gsc)) return -EBUSY; if (p->disp) { gsc_pm_qos_ctrl(gsc, GSC_QOS_ON, 267000, 200000); media_entity_pipeline_start(&p->disp->entity, p->pipe); } else if (p->sensor) { media_entity_pipeline_start(&p->sensor->entity, p->pipe); } else { gsc_err("Error pipeline"); return -EPIPE; } ret = gsc_cap_link_validate(gsc); if (ret) return ret; gsc_hw_set_sw_reset(gsc); ret= gsc_wait_reset(gsc); if (ret < 0) { gsc_err("gscaler s/w reset timeout"); return ret; } gsc_hw_set_output_buf_mask_all(gsc); return vb2_streamon(&gsc->cap.vbq, type); }
int gsc_set_scaler_info(struct gsc_ctx *ctx) { struct gsc_scaler *sc = &ctx->scaler; struct gsc_frame *s_frame = &ctx->s_frame; struct gsc_frame *d_frame = &ctx->d_frame; struct gsc_variant *variant = ctx->gsc_dev->variant; int tx, ty; int ret; ret = gsc_check_scaler_ratio(variant, s_frame->crop.width, s_frame->crop.height, d_frame->crop.width, d_frame->crop.height, ctx->gsc_ctrls.rotate->val, ctx->out_path); if (ret) { gsc_err("out of scaler range"); return ret; } if (ctx->gsc_ctrls.rotate->val == 90 || ctx->gsc_ctrls.rotate->val == 270) { ty = d_frame->crop.width; tx = d_frame->crop.height; } else { tx = d_frame->crop.width; ty = d_frame->crop.height; } ret = gsc_cal_prescaler_ratio(variant, s_frame->crop.width, tx, &sc->pre_hratio); if (ret) { gsc_err("Horizontal scale ratio is out of range"); return ret; } ret = gsc_cal_prescaler_ratio(variant, s_frame->crop.height, ty, &sc->pre_vratio); if (ret) { gsc_err("Vertical scale ratio is out of range"); return ret; } gsc_check_src_scale_info(variant, s_frame, &sc->pre_hratio, tx, ty, &sc->pre_vratio); gsc_get_prescaler_shfactor(sc->pre_hratio, sc->pre_vratio, &sc->pre_shfactor); sc->main_hratio = (s_frame->crop.width << 16) / tx; sc->main_vratio = (s_frame->crop.height << 16) / ty; gsc_dbg("scaler input/output size : sx = %d, sy = %d, tx = %d, ty = %d", s_frame->crop.width, s_frame->crop.height, tx, ty); gsc_dbg("scaler ratio info : pre_shfactor : %d, pre_h : %d, pre_v :%d,\ main_h : %ld, main_v : %ld", sc->pre_shfactor, sc->pre_hratio, sc->pre_vratio, sc->main_hratio, sc->main_vratio); return 0; }
static int gsc_capture_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], void *allocators[]) { struct gsc_ctx *ctx = vq->drv_priv; struct gsc_fmt *ffmt = ctx->d_frame.fmt; int i, ret = 0; if (!ffmt) return -EINVAL; *num_planes = ffmt->num_planes; for (i = 0; i < ffmt->num_planes; i++) { sizes[i] = get_plane_size(&ctx->d_frame, i); allocators[i] = ctx->gsc_dev->alloc_ctx; } ret = vb2_queue_init(vq); if (ret) { gsc_err("failed to init vb2_queue"); return ret; } return 0; }
static int gsc_capture_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { struct gsc_dev *gsc = video_drvdata(file); struct gsc_ctx *ctx = gsc->cap.ctx; struct gsc_frame *frame; struct v4l2_pix_format_mplane *pix; int i, ret = 0; ret = gsc_capture_try_fmt_mplane(file, fh, f); if (ret) return ret; if (vb2_is_streaming(&gsc->cap.vbq)) { gsc_err("queue (%d) busy", f->type); return -EBUSY; } frame = &ctx->d_frame; pix = &f->fmt.pix_mp; frame->fmt = find_format(&pix->pixelformat, NULL, 0); if (!frame->fmt) return -EINVAL; for (i = 0; i < frame->fmt->nr_comp; i++) frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height; gsc_set_frame_size(frame, pix->width, pix->height); gsc_dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height); return 0; }
static int gsc_capture_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct gsc_dev *gsc = video_drvdata(file); struct gsc_pipeline *p = &gsc->pipeline; int ret; if (gsc_cap_active(gsc)) return -EBUSY; if (p->disp) { media_entity_pipeline_start(&p->disp->entity, p->pipe); } else if (p->sensor) { media_entity_pipeline_start(&p->sensor->entity, p->pipe); } else { gsc_err("Error pipeline"); return -EPIPE; } ret = gsc_cap_link_validate(gsc); if (ret) return ret; return vb2_streamon(&gsc->cap.vbq, type); }
static int gsc_m2m_release(struct file *file) { struct gsc_ctx *ctx = fh_to_ctx(file->private_data); struct gsc_dev *gsc = ctx->gsc_dev; gsc_dbg("pid: %d, state: 0x%lx, refcnt= %d", task_pid_nr(current), gsc->state, gsc->m2m.refcnt); v4l2_m2m_ctx_release(ctx->m2m_ctx); gsc_ctrls_delete(ctx); v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); if (--gsc->m2m.refcnt <= 0) clear_bit(ST_M2M_OPEN, &gsc->state); /* This is unnormal case */ if (gsc->protected_content) { int id = gsc->id + 3; gsc_err("DRM should be disabled before device close"); exynos_smc(SMC_PROTECTION_SET, 0, id, 0); gsc_set_protected_content(gsc, false); } kfree(ctx); return 0; }
int gsc_wait_stop(struct gsc_dev *dev) { unsigned long timeo = jiffies + 10; /* timeout of 50ms */ u32 cfg; int ret; while (time_before(jiffies, timeo)) { cfg = readl(dev->regs + GSC_ENABLE); if (!(cfg & GSC_ENABLE_OP_STATUS)) return 0; usleep_range(10, 20); } /* This is workaround until next chips. * If fimd is stop than gsc, gsc didn't work complete */ gsc_hw_set_sw_reset(dev); ret = gsc_wait_reset(dev); if (ret < 0) { gsc_err("gscaler s/w reset timeout"); return ret; } gsc_hw_set_pixelasync_reset_output(dev); gsc_info("wait time : %d ms", jiffies_to_msecs(jiffies - timeo + 10)); return 0; }
static int gsc_capture_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { struct gsc_dev *gsc = video_drvdata(file); struct v4l2_subdev *sd; struct gsc_pipeline *p = &gsc->pipeline; int ret; if (p->disp) { gsc_pm_qos_ctrl(gsc, GSC_QOS_OFF, 0, 0); sd = gsc->pipeline.disp; } else if (p->sensor) { sd = gsc->pipeline.sensor; } else { gsc_err("Error pipeline"); return -EPIPE; } ret = vb2_streamoff(&gsc->cap.vbq, type); if (ret == 0) { if (p->disp) media_entity_pipeline_stop(&p->disp->entity); else if (p->sensor) media_entity_pipeline_stop(&p->sensor->entity); } return ret; }
static int gsc_m2m_open(struct file *file) { struct gsc_dev *gsc = video_drvdata(file); struct gsc_ctx *ctx = NULL; int ret; gsc_dbg("pid: %d, state: 0x%lx", task_pid_nr(current), gsc->state); if (gsc_out_opened(gsc) || gsc_cap_opened(gsc)) return -EBUSY; ctx = kzalloc(sizeof *ctx, GFP_KERNEL); if (!ctx) return -ENOMEM; v4l2_fh_init(&ctx->fh, gsc->m2m.vfd); ret = gsc_ctrls_create(ctx); if (ret) goto error_fh; /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; file->private_data = &ctx->fh; v4l2_fh_add(&ctx->fh); ctx->gsc_dev = gsc; /* Default color format */ ctx->s_frame.fmt = get_format(0); ctx->d_frame.fmt = get_format(0); /* Setup the device context for mem2mem mode. */ ctx->state |= GSC_CTX_M2M; ctx->flags = 0; ctx->in_path = GSC_DMA; ctx->out_path = GSC_DMA; spin_lock_init(&ctx->slock); INIT_LIST_HEAD(&ctx->fence_wait_list); INIT_WORK(&ctx->fence_work, gsc_m2m_fence_work); ctx->m2m_ctx = v4l2_m2m_ctx_init(gsc->m2m.m2m_dev, ctx, queue_init); if (IS_ERR(ctx->m2m_ctx)) { gsc_err("Failed to initialize m2m context"); ret = PTR_ERR(ctx->m2m_ctx); goto error_fh; } if (gsc->m2m.refcnt++ == 0) set_bit(ST_M2M_OPEN, &gsc->state); gsc_dbg("gsc m2m driver is opened, ctx(0x%p)", ctx); return 0; error_fh: v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); kfree(ctx); return ret; }
static int gsc_capture_create_link(struct gsc_dev *gsc) { struct media_entity *source, *sink; struct exynos_platform_gscaler *pdata = gsc->pdata; struct exynos_isp_info *isp_info; u32 num_clients = pdata->num_clients; int ret, i; enum cam_port id; /* GSC-SUBDEV ------> GSC-VIDEO (Always link enable) */ source = &gsc->cap.sd_cap->entity; sink = &gsc->cap.vfd->entity; if (source && sink) { ret = media_entity_create_link(source, GSC_PAD_SOURCE, sink, 0, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) { gsc_err("failed link flite to gsc\n"); return ret; } } for (i = 0; i < num_clients; i++) { isp_info = pdata->isp_info[i]; id = isp_info->cam_port; /* FIMC-LITE ------> GSC-SUBDEV (ITU & MIPI common) */ source = &gsc->cap.sd_flite[id]->entity; sink = &gsc->cap.sd_cap->entity; if (source && sink) { if (pdata->cam_preview) ret = media_entity_create_link(source, FLITE_PAD_SOURCE_PREV, sink, GSC_PAD_SINK, 0); if (!ret && pdata->cam_camcording) ret = media_entity_create_link(source, FLITE_PAD_SOURCE_CAMCORD, sink, GSC_PAD_SINK, 0); if (ret) { gsc_err("failed link flite to gsc\n"); return ret; } } } return 0; }
int gsc_out_link_validate(const struct media_pad *source, const struct media_pad *sink) { struct v4l2_subdev_format src_fmt; struct v4l2_subdev_crop dst_crop; struct v4l2_subdev *sd; struct gsc_dev *gsc; struct gsc_frame *f; int ret; if (media_entity_type(source->entity) != MEDIA_ENT_T_V4L2_SUBDEV || media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) { gsc_err("media entity type isn't subdev\n"); return 0; } sd = media_entity_to_v4l2_subdev(source->entity); gsc = entity_data_to_gsc(v4l2_get_subdevdata(sd)); f = &gsc->out.ctx->d_frame; src_fmt.format.width = f->crop.width; src_fmt.format.height = f->crop.height; src_fmt.format.code = f->fmt->mbus_code; sd = media_entity_to_v4l2_subdev(sink->entity); /* To check if G-Scaler destination size and Mixer destinatin size are the same */ dst_crop.pad = sink->index; dst_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(sd, pad, get_crop, NULL, &dst_crop); if (ret < 0 && ret != -ENOIOCTLCMD) { gsc_err("subdev get_fmt is failed\n"); return -EPIPE; } if (src_fmt.format.width != dst_crop.rect.width || src_fmt.format.height != dst_crop.rect.height) { gsc_err("sink and source format is different\ src_fmt.w = %d, src_fmt.h = %d,\ dst_crop.w = %d, dst_crop.h = %d, rotation = %d", src_fmt.format.width, src_fmt.format.height, dst_crop.rect.width, dst_crop.rect.height, gsc->out.ctx->gsc_ctrls.rotate->val); return -EINVAL; }
u32 get_plane_size(struct gsc_frame *frame, unsigned int plane) { if (!frame || plane >= frame->fmt->num_planes) { gsc_err("Invalid argument"); return 0; } return frame->payload[plane]; }
void gsc_op_timer_handler(unsigned long arg) { struct gsc_ctx *ctx = (struct gsc_ctx *)arg; struct gsc_dev *gsc = ctx->gsc_dev; struct vb2_buffer *src_vb, *dst_vb; clear_bit(ST_M2M_RUN, &gsc->state); pm_runtime_put_sync(&gsc->pdev->dev); src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); if (src_vb && dst_vb) { v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR); v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR); } gsc_err("GSCALER[%d] interrupt hasn't been triggered", gsc->id); gsc_err("erro ctx: %p, ctx->state: 0x%x", ctx, ctx->state); }
static int gsc_capture_open(struct file *file) { struct gsc_dev *gsc = video_drvdata(file); int ret = v4l2_fh_open(file); if (ret) return ret; if (gsc_m2m_opened(gsc) || gsc_out_opened(gsc) || gsc_cap_opened(gsc)) { v4l2_fh_release(file); return -EBUSY; } set_bit(ST_CAPT_OPEN, &gsc->state); pm_runtime_get_sync(&gsc->pdev->dev); if (++gsc->cap.refcnt == 1) { ret = gsc_cap_pipeline_initialize(gsc, &gsc->cap.vfd->entity, true); if (ret < 0) { gsc_err("gsc pipeline initialization failed\n"); goto err; } ret = gsc_capture_ctrls_create(gsc); if (ret) { gsc_err("failed to create controls\n"); goto err; } } gsc_dbg("pid: %d, state: 0x%lx", task_pid_nr(current), gsc->state); return 0; err: pm_runtime_put_sync(&gsc->pdev->dev); v4l2_fh_release(file); clear_bit(ST_CAPT_OPEN, &gsc->state); return ret; }
static int gsc_clk_enable_for_wb(struct gsc_dev *gsc) { struct clk *gsd; int ret = 0; gsd = devm_clk_get(&gsc->pdev->dev, "gate_gsd"); if (IS_ERR(gsd)) { gsc_err("fail to get gsd clock"); return PTR_ERR(gsd); } ret = clk_prepare_enable(gsd); if (ret) { gsc_err("fail to enable gsd"); return -EINVAL; } clk_put(gsd); return 0; }
static int gsc_capture_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct gsc_dev *gsc = video_drvdata(file); if (gsc_cap_active(gsc)) { gsc_err("gsc didn't stop complete"); return -EBUSY; } return vb2_streamon(&gsc->cap.vbq, type); }
static int gsc_cap_stop_capture(struct gsc_dev *gsc) { int ret; gsc_dbg("G-Scaler h/w disable control"); ret = wait_event_timeout(gsc->irq_queue, !test_bit(ST_CAPT_RUN, &gsc->state), GSC_SHUTDOWN_TIMEOUT); if (ret == 0) { gsc_err("wait timeout"); return -EBUSY; } return 0; }
static int gsc_cap_check_limit_size(struct gsc_dev *gsc, unsigned int pad, struct v4l2_mbus_framefmt *fmt) { struct gsc_variant *variant = gsc->variant; u32 src_crop = fmt->width * fmt->height; u32 max_src_size = variant->pix_max->otf_w * variant->pix_max->otf_h; switch (pad) { case GSC_PAD_SINK: if (src_crop > max_src_size) { gsc_err("%d x %d is not supported", fmt->width, fmt->height); return -EINVAL; } break; default: gsc_err("unsupported pad"); return -EINVAL; } return 0; }
static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) { struct gsc_ctx *ctx = priv; int ret; memset(src_vq, 0, sizeof(*src_vq)); src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; src_vq->drv_priv = ctx; src_vq->ops = &gsc_m2m_qops; src_vq->mem_ops = ctx->gsc_dev->vb2->ops; src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ret = vb2_queue_init(src_vq); if (ret) { gsc_err("failed to init vb2_queue"); return ret; } memset(dst_vq, 0, sizeof(*dst_vq)); dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; dst_vq->drv_priv = ctx; dst_vq->ops = &gsc_m2m_qops; dst_vq->mem_ops = ctx->gsc_dev->vb2->ops; dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ret = vb2_queue_init(dst_vq); if (ret) { gsc_err("failed to init vb2_queue"); return ret; } return ret; }
static int gsc_clk_disable_for_wb(struct gsc_dev *gsc) { struct clk *gsd; gsd = devm_clk_get(&gsc->pdev->dev, "gate_gsd"); if (IS_ERR(gsd)) { gsc_err("fail to get gsd clock"); return PTR_ERR(gsd); } clk_disable_unprepare(gsd); clk_put(gsd); return 0; }
static int gsc_cap_set_addr(struct gsc_dev *gsc,struct gsc_ctx *ctx, struct gsc_input_buf *buf, int index) { int ret; ret = gsc_prepare_addr(ctx, &buf->vb, &ctx->d_frame, &ctx->d_frame.addr); if (ret) { gsc_err("Prepare G-Scaler address failed\n"); return -EINVAL; } if (!ctx->d_frame.addr.y) { gsc_err("source address is null"); return -EINVAL; } buf->addr = ctx->d_frame.addr; list_add_tail(&buf->list, &gsc->cap.active_buf_q); gsc_hw_set_output_addr_fixed(gsc, &ctx->d_frame.addr); buf->idx = index; return 0; }
u32 get_plane_info(struct gsc_frame frm, u32 addr, u32 *index) { if (frm.addr.y == addr) { *index = 0; return frm.addr.y; } else if (frm.addr.cb == addr) { *index = 1; return frm.addr.cb; } else if (frm.addr.cr == addr) { *index = 2; return frm.addr.cr; } else { gsc_err("Plane address is wrong"); return -EINVAL; } }
int gsc_cal_prescaler_ratio(struct gsc_variant *var, u32 src, u32 dst, u32 *ratio) { if ((dst > src) || (dst >= src / var->poly_sc_down_max)) { *ratio = 1; return 0; } if ((src / var->poly_sc_down_max / var->pre_sc_down_max) > dst) { gsc_err("scale ratio exceeded maximun scale down ratio(1/16)"); return -EINVAL; } *ratio = (dst > (src / 8)) ? 2 : 4; return 0; }
static int gsc_capture_set_addr(struct vb2_buffer *vb) { struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct gsc_dev *gsc = ctx->gsc_dev; int ret; ret = gsc_prepare_addr(ctx, vb, &ctx->d_frame, &ctx->d_frame.addr); if (ret) { gsc_err("Prepare G-Scaler address failed\n"); return -EINVAL; } gsc_hw_set_output_addr(gsc, &ctx->d_frame.addr, vb->v4l2_buf.index); return 0; }
static int gsc_cap_register_sensor_entities(struct gsc_dev *gsc) { struct exynos_platform_gscaler *pdata = gsc->pdata; u32 num_clients = pdata->num_clients; int i; for (i = 0; i < num_clients; i++) { gsc->cap.sensor[i].pdata = pdata->isp_info[i]; gsc->cap.sensor[i].sd = gsc_cap_register_sensor(gsc, i); if (IS_ERR_OR_NULL(gsc->cap.sensor[i].sd)) { gsc_err("failed to get register sensor"); return -EINVAL; } } return 0; }
static int gsc_m2m_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { struct gsc_ctx *ctx = fh_to_ctx(fh); struct vb2_queue *vq; struct gsc_frame *frame; struct v4l2_pix_format_mplane *pix; int i, ret = 0; ret = gsc_m2m_try_fmt_mplane(file, fh, f); if (ret) return ret; vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); if (vb2_is_streaming(vq)) { gsc_err("queue (%d) busy", f->type); return -EBUSY; } if (V4L2_TYPE_IS_OUTPUT(f->type)) { frame = &ctx->s_frame; } else { frame = &ctx->d_frame; } pix = &f->fmt.pix_mp; frame->fmt = find_format(&pix->pixelformat, NULL, 0); if (!frame->fmt) return -EINVAL; for (i = 0; i < frame->fmt->num_planes; i++) frame->payload[i] = pix->plane_fmt[i].sizeimage; gsc_set_frame_size(frame, pix->width, pix->height); if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) gsc_ctx_state_lock_set(GSC_PARAMS | GSC_DST_FMT, ctx); else gsc_ctx_state_lock_set(GSC_PARAMS | GSC_SRC_FMT, ctx); gsc_dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height); return 0; }