diff options
Diffstat (limited to 'drivers/staging/media/atomisp/pci/atomisp_subdev.c')
-rw-r--r-- | drivers/staging/media/atomisp/pci/atomisp_subdev.c | 102 |
1 files changed, 52 insertions, 50 deletions
diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index a87fc74159e2..3a3e84a035e2 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -31,6 +31,7 @@ #include "atomisp_compat.h" #include "atomisp_fops.h" #include "atomisp_internal.h" +#include "atomisp_ioctl.h" const struct atomisp_in_fmt_conv atomisp_in_fmt_conv[] = { { MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_BGGR }, @@ -148,18 +149,6 @@ static long isp_subdev_ioctl(struct v4l2_subdev *sd, return 0; } -/* - * isp_subdev_set_power - Power on/off the CCDC module - * @sd: ISP V4L2 subdevice - * @on: power on/off - * - * Return 0 on success or a negative error code otherwise. - */ -static int isp_subdev_set_power(struct v4l2_subdev *sd, int on) -{ - return 0; -} - static int isp_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub) @@ -287,35 +276,6 @@ static void isp_get_fmt_rect(struct v4l2_subdev *sd, } } -static void isp_subdev_propagate(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - u32 which, uint32_t pad, uint32_t target, - uint32_t flags) -{ - struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM]; - struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM], - *comp[ATOMISP_SUBDEV_PADS_NUM]; - - if (flags & V4L2_SEL_FLAG_KEEP_CONFIG) - return; - - isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp); - - switch (pad) { - case ATOMISP_SUBDEV_PAD_SINK: { - struct v4l2_rect r = {0}; - - /* Only crop target supported on sink pad. */ - r.width = ffmt[pad]->width; - r.height = ffmt[pad]->height; - - atomisp_subdev_set_selection(sd, sd_state, which, pad, - target, flags, &r); - break; - } - } -} - static int isp_subdev_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_selection *sel) @@ -390,11 +350,12 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, if (isp_sd->params.video_dis_en && isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { - /* This resolution contains 20 % of DVS slack + /* + * This resolution contains 20 % of DVS slack * (of the desired captured image before * scaling, or 1 / 6 of what we get from the - * sensor) in both width and height. Remove - * it. */ + * sensor) in both width and height. Remove it. + */ crop[pad]->width = roundup(crop[pad]->width * 5 / 6, ATOM_ISP_STEP_WIDTH); crop[pad]->height = roundup(crop[pad]->height * 5 / 6, @@ -541,6 +502,7 @@ void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd, case ATOMISP_SUBDEV_PAD_SINK: { const struct atomisp_in_fmt_conv *fc = atomisp_find_in_fmt_conv(ffmt->code); + struct v4l2_rect r = {}; if (!fc) { fc = atomisp_in_fmt_conv; @@ -551,8 +513,12 @@ void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd, *__ffmt = *ffmt; - isp_subdev_propagate(sd, sd_state, which, pad, - V4L2_SEL_TGT_CROP, 0); + /* Propagate new ffmt to selection */ + r.width = ffmt->width; + r.height = ffmt->height; + /* Only crop target supported on sink pad. */ + atomisp_subdev_set_selection(sd, sd_state, which, pad, + V4L2_SEL_TGT_CROP, 0, &r); if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { atomisp_css_input_set_resolution(isp_sd, @@ -618,7 +584,7 @@ static int isp_subdev_set_format(struct v4l2_subdev *sd, /* V4L2 subdev core operations */ static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = { - .ioctl = isp_subdev_ioctl, .s_power = isp_subdev_set_power, + .ioctl = isp_subdev_ioctl, .subscribe_event = isp_subdev_subscribe_event, .unsubscribe_event = isp_subdev_unsubscribe_event, }; @@ -658,8 +624,45 @@ static void isp_subdev_init_params(struct atomisp_sub_device *asd) } /* media operations */ +static int atomisp_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ + struct v4l2_subdev *sd = container_of(entity, struct v4l2_subdev, + entity); + struct atomisp_sub_device *asd = v4l2_get_subdevdata(sd); + struct atomisp_device *isp = asd->isp; + int i; + + /* ISP's source is immutable */ + if (local != &asd->pads[ATOMISP_SUBDEV_PAD_SINK]) { + v4l2_err(sd, "Error pad %d does not support changing flags\n", + local->index); + return -EINVAL; + } + + for (i = 0; i < isp->input_cnt; i++) { + if (&isp->inputs[i].csi_port->entity.pads[CSI2_PAD_SOURCE] == remote) + break; + } + + if (i == isp->input_cnt) { + v4l2_err(sd, "Error no sensor for selected CSI receiver\n"); + return -EINVAL; + } + + /* Turn off the sensor on link disable */ + if (!(flags & MEDIA_LNK_FL_ENABLED)) { + atomisp_s_sensor_power(isp, i, 0); + return 0; + } + + return atomisp_select_input(isp, i); +} + static const struct media_entity_operations isp_subdev_media_ops = { .link_validate = v4l2_subdev_link_validate, + .link_setup = atomisp_link_setup, /* .set_power = v4l2_subdev_set_power, */ }; @@ -789,7 +792,7 @@ static int atomisp_init_subdev_pipe(struct atomisp_sub_device *asd, /* Init videobuf2 queue structure */ pipe->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - pipe->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR; + pipe->vb_queue.io_modes = VB2_MMAP | VB2_DMABUF; pipe->vb_queue.buf_struct_size = sizeof(struct ia_css_frame); pipe->vb_queue.ops = &atomisp_vb2_ops; pipe->vb_queue.mem_ops = &vb2_vmalloc_memops; @@ -823,10 +826,9 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) int ret; v4l2_subdev_init(sd, &isp_subdev_v4l2_ops); - sprintf(sd->name, "ATOMISP_SUBDEV"); + sprintf(sd->name, "Atom ISP"); v4l2_set_subdevdata(sd, asd); sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; - sd->devnode = &asd->video_out.vdev; pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK; pads[ATOMISP_SUBDEV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; |