summaryrefslogtreecommitdiff
path: root/drivers/staging/media/atomisp/pci/atomisp_subdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media/atomisp/pci/atomisp_subdev.c')
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.c102
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;