Advertisement
Guest User

mxc_v4l2_capture.c

a guest
Apr 21st, 2013
706
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 74.02 KB | None | 0 0
  1. /*
  2.  * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.
  3.  */
  4.  
  5. /*
  6.  * The code contained herein is licensed under the GNU General Public
  7.  * License. You may obtain a copy of the GNU General Public License
  8.  * Version 2 or later at the following locations:
  9.  *
  10.  * http://www.opensource.org/licenses/gpl-license.html
  11.  * http://www.gnu.org/copyleft/gpl.html
  12.  */
  13.  
  14. /*!
  15.  * @file drivers/media/video/mxc/capture/mxc_v4l2_capture.c
  16.  *
  17.  * @brief Mxc Video For Linux 2 driver
  18.  *
  19.  * @ingroup MXC_V4L2_CAPTURE
  20.  */
  21. #include <linux/version.h>
  22. #include <linux/module.h>
  23. #include <linux/init.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/fs.h>
  26. #include <linux/slab.h>
  27. #include <linux/ctype.h>
  28. #include <linux/io.h>
  29. #include <linux/semaphore.h>
  30. #include <linux/pagemap.h>
  31. #include <linux/vmalloc.h>
  32. #include <linux/types.h>
  33. #include <linux/fb.h>
  34. #include <linux/dma-mapping.h>
  35. #include <linux/mxcfb.h>
  36. #include <media/v4l2-chip-ident.h>
  37. #include <media/v4l2-ioctl.h>
  38. #include <media/v4l2-int-device.h>
  39. #include "mxc_v4l2_capture.h"
  40. #include "ipu_prp_sw.h"
  41.  
  42. static int video_nr = -1, local_buf_num;
  43. static cam_data *g_cam;
  44.  
  45. /*! This data is used for the output to the display. */
  46. #define MXC_V4L2_CAPTURE_NUM_OUTPUTS    3
  47. #define MXC_V4L2_CAPTURE_NUM_INPUTS 2
  48. static struct v4l2_output mxc_capture_outputs[MXC_V4L2_CAPTURE_NUM_OUTPUTS] = {
  49.     {
  50.      .index = 0,
  51.      .name = "DISP3 BG",
  52.      .type = V4L2_OUTPUT_TYPE_ANALOG,
  53.      .audioset = 0,
  54.      .modulator = 0,
  55.      .std = V4L2_STD_UNKNOWN,
  56.      },
  57.     {
  58.      .index = 1,
  59.      .name = "DISP3 BG - DI1",
  60.      .type = V4L2_OUTPUT_TYPE_ANALOG,
  61.      .audioset = 0,
  62.      .modulator = 0,
  63.      .std = V4L2_STD_UNKNOWN,
  64.      },
  65.     {
  66.      .index = 2,
  67.      .name = "DISP3 FG",
  68.      .type = V4L2_OUTPUT_TYPE_ANALOG,
  69.      .audioset = 0,
  70.      .modulator = 0,
  71.      .std = V4L2_STD_UNKNOWN,
  72.      },
  73. };
  74.  
  75. static struct v4l2_input mxc_capture_inputs[MXC_V4L2_CAPTURE_NUM_INPUTS] = {
  76.     {
  77.      .index = 0,
  78.      .name = "CSI IC MEM",
  79.      .type = V4L2_INPUT_TYPE_CAMERA,
  80.      .audioset = 0,
  81.      .tuner = 0,
  82.      .std = V4L2_STD_UNKNOWN,
  83.      .status = 0,
  84.      },
  85.     {
  86.      .index = 1,
  87.      .name = "CSI MEM",
  88.      .type = V4L2_INPUT_TYPE_CAMERA,
  89.      .audioset = 0,
  90.      .tuner = 0,
  91.      .std = V4L2_STD_UNKNOWN,
  92.      .status = V4L2_IN_ST_NO_POWER,
  93.      },
  94. };
  95.  
  96. /*! List of TV input video formats supported. The video formats is corresponding
  97.  * to the v4l2_id in video_fmt_t.
  98.  * Currently, only PAL and NTSC is supported. Needs to be expanded in the
  99.  * future.
  100.  */
  101. typedef enum {
  102.     TV_NTSC = 0,        /*!< Locked on (M) NTSC video signal. */
  103.     TV_PAL,         /*!< (B, G, H, I, N)PAL video signal. */
  104.     TV_NOT_LOCKED,      /*!< Not locked on a signal. */
  105. } video_fmt_idx;
  106.  
  107. /*! Number of video standards supported (including 'not locked' signal). */
  108. #define TV_STD_MAX      (TV_NOT_LOCKED + 1)
  109.  
  110. /*! Video format structure. */
  111. typedef struct {
  112.     int v4l2_id;        /*!< Video for linux ID. */
  113.     char name[16];      /*!< Name (e.g., "NTSC", "PAL", etc.) */
  114.     u16 raw_width;      /*!< Raw width. */
  115.     u16 raw_height;     /*!< Raw height. */
  116.     u16 active_width;   /*!< Active width. */
  117.     u16 active_height;  /*!< Active height. */
  118.     u16 active_top;     /*!< Active top. */
  119.     u16 active_left;    /*!< Active left. */
  120. } video_fmt_t;
  121.  
  122. /*!
  123.  * Description of video formats supported.
  124.  *
  125.  *  PAL: raw=720x625, active=720x576.
  126.  *  NTSC: raw=720x525, active=720x480.
  127.  */
  128. static video_fmt_t video_fmts[] = {
  129.     {           /*! NTSC */
  130.      .v4l2_id = V4L2_STD_NTSC,
  131.      .name = "NTSC",
  132.      .raw_width = 720,      /* SENS_FRM_WIDTH */
  133.      .raw_height = 525,     /* SENS_FRM_HEIGHT */
  134.      .active_width = 720,       /* ACT_FRM_WIDTH */
  135.      .active_height = 480,      /* ACT_FRM_HEIGHT */
  136.      .active_top = 13,
  137.      .active_left = 0,
  138.      },
  139.     {           /*! (B, G, H, I, N) PAL */
  140.      .v4l2_id = V4L2_STD_PAL,
  141.      .name = "PAL",
  142.      .raw_width = 720,
  143.      .raw_height = 625,
  144.      .active_width = 720,
  145.      .active_height = 576,
  146.      .active_top = 0,
  147.      .active_left = 0,
  148.      },
  149.     {           /*! Unlocked standard */
  150.      .v4l2_id = V4L2_STD_ALL,
  151.      .name = "Autodetect",
  152.      .raw_width = 720,
  153.      .raw_height = 625,
  154.      .active_width = 720,
  155.      .active_height = 576,
  156.      .active_top = 0,
  157.      .active_left = 0,
  158.      },
  159. };
  160.  
  161. /*!* Standard index of TV. */
  162. static video_fmt_idx video_index = TV_NOT_LOCKED;
  163.  
  164. static int mxc_v4l2_master_attach(struct v4l2_int_device *slave);
  165. static void mxc_v4l2_master_detach(struct v4l2_int_device *slave);
  166. static int start_preview(cam_data *cam);
  167. static int stop_preview(cam_data *cam);
  168.  
  169. /*! Information about this driver. */
  170. static struct v4l2_int_master mxc_v4l2_master = {
  171.     .attach = mxc_v4l2_master_attach,
  172.     .detach = mxc_v4l2_master_detach,
  173. };
  174.  
  175. static struct v4l2_int_device mxc_v4l2_int_device = {
  176.     .module = THIS_MODULE,
  177.     .name = "mxc_v4l2_cap",
  178.     .type = v4l2_int_type_master,
  179.     .u = {
  180.         .master = &mxc_v4l2_master,
  181.         },
  182. };
  183.  
  184. /***************************************************************************
  185.  * Functions for handling Frame buffers.
  186.  **************************************************************************/
  187.  
  188. /*!
  189.  * Free frame buffers
  190.  *
  191.  * @param cam      Structure cam_data *
  192.  *
  193.  * @return status  0 success.
  194.  */
  195. static int mxc_free_frame_buf(cam_data *cam)
  196. {
  197.     int i;
  198.  
  199.     pr_debug("MVC: In mxc_free_frame_buf\n");
  200.  
  201.     for (i = 0; i < FRAME_NUM; i++) {
  202.         if (cam->frame[i].vaddress != 0) {
  203.             dma_free_coherent(0, cam->frame[i].buffer.length,
  204.                       cam->frame[i].vaddress,
  205.                       cam->frame[i].paddress);
  206.             cam->frame[i].vaddress = 0;
  207.         }
  208.     }
  209.  
  210.     return 0;
  211. }
  212.  
  213. /*!
  214.  * Allocate frame buffers
  215.  *
  216.  * @param cam      Structure cam_data*
  217.  * @param count    int number of buffer need to allocated
  218.  *
  219.  * @return status  -0 Successfully allocated a buffer, -ENOBUFS failed.
  220.  */
  221. static int mxc_allocate_frame_buf(cam_data *cam, int count)
  222. {
  223.     int i;
  224.  
  225.     pr_debug("In MVC:mxc_allocate_frame_buf - size=%d\n",
  226.         cam->v2f.fmt.pix.sizeimage);
  227.  
  228.     for (i = 0; i < count; i++) {
  229.         cam->frame[i].vaddress =
  230.             dma_alloc_coherent(0,
  231.                        PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
  232.                        &cam->frame[i].paddress,
  233.                        GFP_DMA | GFP_KERNEL);
  234.         if (cam->frame[i].vaddress == 0) {
  235.             pr_err("ERROR: v4l2 capture: "
  236.                 "mxc_allocate_frame_buf failed.\n");
  237.             mxc_free_frame_buf(cam);
  238.             return -ENOBUFS;
  239.         }
  240.         cam->frame[i].buffer.index = i;
  241.         cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED;
  242.         cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  243.         cam->frame[i].buffer.length =
  244.             PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
  245.         cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP;
  246.         cam->frame[i].buffer.m.offset = cam->frame[i].paddress;
  247.         cam->frame[i].index = i;
  248.     }
  249.  
  250.     return 0;
  251. }
  252.  
  253. /*!
  254.  * Free frame buffers status
  255.  *
  256.  * @param cam    Structure cam_data *
  257.  *
  258.  * @return none
  259.  */
  260. static void mxc_free_frames(cam_data *cam)
  261. {
  262.     int i;
  263.  
  264.     pr_debug("In MVC:mxc_free_frames\n");
  265.  
  266.     for (i = 0; i < FRAME_NUM; i++) {
  267.         cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED;
  268.     }
  269.  
  270.     cam->enc_counter = 0;
  271.     INIT_LIST_HEAD(&cam->ready_q);
  272.     INIT_LIST_HEAD(&cam->working_q);
  273.     INIT_LIST_HEAD(&cam->done_q);
  274. }
  275.  
  276. /*!
  277.  * Return the buffer status
  278.  *
  279.  * @param cam      Structure cam_data *
  280.  * @param buf      Structure v4l2_buffer *
  281.  *
  282.  * @return status  0 success, EINVAL failed.
  283.  */
  284. static int mxc_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf)
  285. {
  286.     pr_debug("In MVC:mxc_v4l2_buffer_status\n");
  287.  
  288.     if (buf->index < 0 || buf->index >= FRAME_NUM) {
  289.         pr_err("ERROR: v4l2 capture: mxc_v4l2_buffer_status buffers "
  290.                "not allocated\n");
  291.         return -EINVAL;
  292.     }
  293.  
  294.     memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf));
  295.     return 0;
  296. }
  297.  
  298. /***************************************************************************
  299.  * Functions for handling the video stream.
  300.  **************************************************************************/
  301.  
  302. /*!
  303.  * Indicates whether the palette is supported.
  304.  *
  305.  * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_BGR24 or V4L2_PIX_FMT_BGR32
  306.  *
  307.  * @return 0 if failed
  308.  */
  309. static inline int valid_mode(u32 palette)
  310. {
  311.     return ((palette == V4L2_PIX_FMT_RGB565) ||
  312.         (palette == V4L2_PIX_FMT_BGR24) ||
  313.         (palette == V4L2_PIX_FMT_RGB24) ||
  314.         (palette == V4L2_PIX_FMT_BGR32) ||
  315.         (palette == V4L2_PIX_FMT_RGB32) ||
  316.         (palette == V4L2_PIX_FMT_YUV422P) ||
  317.         (palette == V4L2_PIX_FMT_UYVY) ||
  318.         (palette == V4L2_PIX_FMT_YUYV) ||
  319.         (palette == V4L2_PIX_FMT_YUV420) ||
  320.         (palette == V4L2_PIX_FMT_NV12));
  321. }
  322.  
  323. /*!
  324.  * Start the encoder job
  325.  *
  326.  * @param cam      structure cam_data *
  327.  *
  328.  * @return status  0 Success
  329.  */
  330. static int mxc_streamon(cam_data *cam)
  331. {
  332.     struct mxc_v4l_frame *frame;
  333.     int err = 0;
  334.  
  335.     pr_debug("In MVC:mxc_streamon\n");
  336.  
  337.     if (NULL == cam) {
  338.         pr_err("ERROR! cam parameter is NULL\n");
  339.         return -1;
  340.     }
  341.  
  342.     if (cam->capture_on) {
  343.         pr_err("ERROR: v4l2 capture: Capture stream has been turned "
  344.                " on\n");
  345.         return -1;
  346.     }
  347.  
  348.     if (list_empty(&cam->ready_q)) {
  349.         pr_err("ERROR: v4l2 capture: mxc_streamon buffer has not been "
  350.             "queued yet\n");
  351.         return -EINVAL;
  352.     }
  353.  
  354.     cam->capture_pid = current->pid;
  355.  
  356.     if (cam->overlay_on == true)
  357.         stop_preview(cam);
  358.  
  359.     if (cam->enc_enable) {
  360.         err = cam->enc_enable(cam);
  361.         if (err != 0) {
  362.             return err;
  363.         }
  364.     }
  365.  
  366.     cam->ping_pong_csi = 0;
  367.     local_buf_num = 0;
  368.     if (cam->enc_update_eba) {
  369.         frame =
  370.             list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
  371.         list_del(cam->ready_q.next);
  372.         list_add_tail(&frame->queue, &cam->working_q);
  373.         frame->ipu_buf_num = cam->ping_pong_csi;
  374.         err = cam->enc_update_eba(frame->buffer.m.offset,
  375.                       &cam->ping_pong_csi);
  376.  
  377.         frame =
  378.             list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
  379.         list_del(cam->ready_q.next);
  380.         list_add_tail(&frame->queue, &cam->working_q);
  381.         frame->ipu_buf_num = cam->ping_pong_csi;
  382.         err |= cam->enc_update_eba(frame->buffer.m.offset,
  383.                        &cam->ping_pong_csi);
  384.     } else {
  385.         return -EINVAL;
  386.     }
  387.  
  388.     if (cam->overlay_on == true)
  389.         start_preview(cam);
  390.  
  391.     if (cam->enc_enable_csi) {
  392.         err = cam->enc_enable_csi(cam);
  393.         if (err != 0)
  394.             return err;
  395.     }
  396.  
  397.     cam->capture_on = true;
  398.  
  399.     return err;
  400. }
  401.  
  402. /*!
  403.  * Shut down the encoder job
  404.  *
  405.  * @param cam      structure cam_data *
  406.  *
  407.  * @return status  0 Success
  408.  */
  409. static int mxc_streamoff(cam_data *cam)
  410. {
  411.     int err = 0;
  412.  
  413.     pr_debug("In MVC:mxc_streamoff\n");
  414.  
  415.     if (cam->capture_on == false)
  416.         return 0;
  417.  
  418.     if (cam->enc_disable_csi) {
  419.         err = cam->enc_disable_csi(cam);
  420.         if (err != 0)
  421.             return err;
  422.     }
  423.     if (cam->enc_disable)
  424.         err = cam->enc_disable(cam);
  425.  
  426.     mxc_free_frames(cam);
  427.     mxc_capture_inputs[cam->current_input].status |= V4L2_IN_ST_NO_POWER;
  428.     cam->capture_on = false;
  429.     return err;
  430. }
  431.  
  432. /*!
  433.  * Valid and adjust the overlay window size, position
  434.  *
  435.  * @param cam      structure cam_data *
  436.  * @param win      struct v4l2_window  *
  437.  *
  438.  * @return 0
  439.  */
  440. static int verify_preview(cam_data *cam, struct v4l2_window *win)
  441. {
  442.     int i = 0, width_bound = 0, height_bound = 0;
  443.     int *width, *height;
  444.     unsigned int ipu_ch = CHAN_NONE;
  445.     struct fb_info *bg_fbi = NULL, *fbi = NULL;
  446.     bool foregound_fb;
  447.     mm_segment_t old_fs;
  448.  
  449.     pr_debug("In MVC: verify_preview\n");
  450.  
  451.     do {
  452.         fbi = (struct fb_info *)registered_fb[i];
  453.         if (fbi == NULL) {
  454.             pr_err("ERROR: verify_preview frame buffer NULL.\n");
  455.             return -1;
  456.         }
  457.  
  458.         /* Which DI supports 2 layers? */
  459.         if (strncmp(fbi->fix.id, "DISP3 BG", 8) == 0) {
  460.             if (fbi->fbops->fb_ioctl) {
  461.                 old_fs = get_fs();
  462.                 set_fs(KERNEL_DS);
  463.                 fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN,
  464.                         (unsigned long)&ipu_ch);
  465.                 set_fs(old_fs);
  466.             }
  467.             if (ipu_ch == MEM_BG_SYNC) {
  468.                 bg_fbi = fbi;
  469.                 pr_debug("Found background frame buffer.\n");
  470.             }
  471.         }
  472.  
  473.         /* Found the frame buffer to preview on. */
  474.         if (strcmp(fbi->fix.id,
  475.                 mxc_capture_outputs[cam->output].name) == 0) {
  476.             if (strcmp(fbi->fix.id, "DISP3 FG") == 0)
  477.                 foregound_fb = true;
  478.  
  479.             cam->overlay_fb = fbi;
  480.             break;
  481.         }
  482.     } while (++i < FB_MAX);
  483.  
  484.     if (foregound_fb) {
  485.         width_bound = bg_fbi->var.xres;
  486.         height_bound = bg_fbi->var.yres;
  487.  
  488.         if (win->w.width + win->w.left > bg_fbi->var.xres ||
  489.             win->w.height + win->w.top > bg_fbi->var.yres) {
  490.             pr_err("ERROR: FG window position exceeds.\n");
  491.             return -1;
  492.         }
  493.     } else {
  494.         /* 4 bytes alignment for BG */
  495.         width_bound = cam->overlay_fb->var.xres;
  496.         height_bound = cam->overlay_fb->var.yres;
  497.  
  498.         if (cam->overlay_fb->var.bits_per_pixel == 24) {
  499.             win->w.left -= win->w.left % 4;
  500.         } else if (cam->overlay_fb->var.bits_per_pixel == 16) {
  501.             win->w.left -= win->w.left % 2;
  502.         }
  503.  
  504.         if (win->w.width + win->w.left > cam->overlay_fb->var.xres)
  505.             win->w.width = cam->overlay_fb->var.xres - win->w.left;
  506.         if (win->w.height + win->w.top > cam->overlay_fb->var.yres)
  507.             win->w.height = cam->overlay_fb->var.yres - win->w.top;
  508.     }
  509.  
  510.     /* stride line limitation */
  511.     win->w.height -= win->w.height % 8;
  512.     win->w.width -= win->w.width % 8;
  513.  
  514.     if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
  515.         height = &win->w.width;
  516.         width = &win->w.height;
  517.     } else {
  518.         width = &win->w.width;
  519.         height = &win->w.height;
  520.     }
  521.  
  522.     if (*width == 0 || *height == 0) {
  523.         pr_err("ERROR: v4l2 capture: width or height"
  524.             " too small.\n");
  525.         return -EINVAL;
  526.     }
  527.  
  528.     if ((cam->crop_bounds.width / *width > 8) ||
  529.         ((cam->crop_bounds.width / *width == 8) &&
  530.          (cam->crop_bounds.width % *width))) {
  531.         *width = cam->crop_bounds.width / 8;
  532.         if (*width % 8)
  533.             *width += 8 - *width % 8;
  534.         if (*width + win->w.left > width_bound) {
  535.             pr_err("ERROR: v4l2 capture: width exceeds "
  536.                 "resize limit.\n");
  537.             return -1;
  538.         }
  539.         pr_err("ERROR: v4l2 capture: width exceeds limit. "
  540.             "Resize to %d.\n",
  541.             *width);
  542.     }
  543.  
  544.     if ((cam->crop_bounds.height / *height > 8) ||
  545.         ((cam->crop_bounds.height / *height == 8) &&
  546.          (cam->crop_bounds.height % *height))) {
  547.         *height = cam->crop_bounds.height / 8;
  548.         if (*height % 8)
  549.             *height += 8 - *height % 8;
  550.         if (*height + win->w.top > height_bound) {
  551.             pr_err("ERROR: v4l2 capture: height exceeds "
  552.                 "resize limit.\n");
  553.             return -1;
  554.         }
  555.         pr_err("ERROR: v4l2 capture: height exceeds limit "
  556.             "resize to %d.\n",
  557.             *height);
  558.     }
  559.  
  560.     return 0;
  561. }
  562.  
  563. /*!
  564.  * start the viewfinder job
  565.  *
  566.  * @param cam      structure cam_data *
  567.  *
  568.  * @return status  0 Success
  569.  */
  570. static int start_preview(cam_data *cam)
  571. {
  572.     int err = 0;
  573.  
  574.     pr_debug("MVC: start_preview\n");
  575.  
  576.     if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY)
  577.         err = prp_vf_sdc_select(cam);
  578.     else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY)
  579.         err = prp_vf_sdc_select_bg(cam);
  580.     if (err != 0)
  581.         return err;
  582.  
  583.     err = cam->vf_start_sdc(cam);
  584.     if (err != 0)
  585.         return err;
  586.  
  587.     if (cam->vf_enable_csi)
  588.         err = cam->vf_enable_csi(cam);
  589.  
  590.     pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
  591.          __func__,
  592.          cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
  593.     pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
  594.          __func__,
  595.          cam->crop_bounds.width, cam->crop_bounds.height);
  596.     pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
  597.          __func__,
  598.          cam->crop_defrect.width, cam->crop_defrect.height);
  599.     pr_debug("End of %s: crop_current widthxheight %d x %d\n",
  600.          __func__,
  601.          cam->crop_current.width, cam->crop_current.height);
  602.  
  603.     return err;
  604. }
  605.  
  606. /*!
  607.  * shut down the viewfinder job
  608.  *
  609.  * @param cam      structure cam_data *
  610.  *
  611.  * @return status  0 Success
  612.  */
  613. static int stop_preview(cam_data *cam)
  614. {
  615.     int err = 0;
  616.  
  617.     pr_debug("MVC: stop preview\n");
  618.  
  619.     if (cam->vf_disable_csi) {
  620.         err = cam->vf_disable_csi(cam);
  621.         if (err != 0)
  622.             return err;
  623.     }
  624.  
  625.     if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY)
  626.         err = prp_vf_sdc_deselect(cam);
  627.     else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY)
  628.         err = prp_vf_sdc_deselect_bg(cam);
  629.  
  630.     return err;
  631. }
  632.  
  633. /***************************************************************************
  634.  * VIDIOC Functions.
  635.  **************************************************************************/
  636.  
  637. /*!
  638.  * V4L2 - mxc_v4l2_g_fmt function
  639.  *
  640.  * @param cam         structure cam_data *
  641.  *
  642.  * @param f           structure v4l2_format *
  643.  *
  644.  * @return  status    0 success, EINVAL failed
  645.  */
  646. static int mxc_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f)
  647. {
  648.     int retval = 0;
  649.  
  650.     pr_debug("In MVC: mxc_v4l2_g_fmt type=%d\n", f->type);
  651.  
  652.     switch (f->type) {
  653.     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
  654.         pr_debug("   type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
  655.         f->fmt.pix = cam->v2f.fmt.pix;
  656.         break;
  657.     case V4L2_BUF_TYPE_VIDEO_OVERLAY:
  658.         pr_debug("   type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
  659.         f->fmt.win = cam->win;
  660.         break;
  661.     default:
  662.         pr_debug("   type is invalid\n");
  663.         retval = -EINVAL;
  664.     }
  665.  
  666.     pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
  667.          __func__,
  668.          cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
  669.     pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
  670.          __func__,
  671.          cam->crop_bounds.width, cam->crop_bounds.height);
  672.     pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
  673.          __func__,
  674.          cam->crop_defrect.width, cam->crop_defrect.height);
  675.     pr_debug("End of %s: crop_current widthxheight %d x %d\n",
  676.          __func__,
  677.          cam->crop_current.width, cam->crop_current.height);
  678.  
  679.     return retval;
  680. }
  681.  
  682. /*!
  683.  * V4L2 - mxc_v4l2_s_fmt function
  684.  *
  685.  * @param cam         structure cam_data *
  686.  *
  687.  * @param f           structure v4l2_format *
  688.  *
  689.  * @return  status    0 success, EINVAL failed
  690.  */
  691. static int mxc_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
  692. {
  693.     int retval = 0;
  694.     int size = 0;
  695.     int bytesperline = 0;
  696.     int *width, *height;
  697.  
  698.     pr_debug("In MVC: mxc_v4l2_s_fmt\n");
  699.  
  700.     switch (f->type) {
  701.     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
  702.         pr_debug("   type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
  703.         if (!valid_mode(f->fmt.pix.pixelformat)) {
  704.             pr_err("ERROR: v4l2 capture: mxc_v4l2_s_fmt: format "
  705.                    "not supported\n");
  706.             return -EINVAL;
  707.         }
  708.  
  709.         /*
  710.          * Force the capture window resolution to be crop bounds
  711.          * for CSI MEM input mode.
  712.          */
  713.         if (strcmp(mxc_capture_inputs[cam->current_input].name,
  714.                "CSI MEM") == 0) {
  715.             f->fmt.pix.width = cam->crop_current.width;
  716.             f->fmt.pix.height = cam->crop_current.height;
  717.         }
  718.  
  719.         if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
  720.             height = &f->fmt.pix.width;
  721.             width = &f->fmt.pix.height;
  722.         } else {
  723.             width = &f->fmt.pix.width;
  724.             height = &f->fmt.pix.height;
  725.         }
  726.  
  727.         /* stride line limitation */
  728.         *width -= *width % 8;
  729.         *height -= *height % 8;
  730.  
  731.         if (*width == 0 || *height == 0) {
  732.             pr_err("ERROR: v4l2 capture: width or height"
  733.                 " too small.\n");
  734.             return -EINVAL;
  735.         }
  736.  
  737.         if ((cam->crop_current.width / *width > 8) ||
  738.             ((cam->crop_current.width / *width == 8) &&
  739.              (cam->crop_current.width % *width))) {
  740.             *width = cam->crop_current.width / 8;
  741.             if (*width % 8)
  742.                 *width += 8 - *width % 8;
  743.             pr_err("ERROR: v4l2 capture: width exceeds limit "
  744.                 "resize to %d.\n",
  745.                    *width);
  746.         }
  747.  
  748.         if ((cam->crop_current.height / *height > 8) ||
  749.             ((cam->crop_current.height / *height == 8) &&
  750.              (cam->crop_current.height % *height))) {
  751.             *height = cam->crop_current.height / 8;
  752.             if (*height % 8)
  753.                 *height += 8 - *height % 8;
  754.             pr_err("ERROR: v4l2 capture: height exceeds limit "
  755.                    "resize to %d.\n",
  756.                    *height);
  757.         }
  758.  
  759.         switch (f->fmt.pix.pixelformat) {
  760.         case V4L2_PIX_FMT_RGB565:
  761.             size = f->fmt.pix.width * f->fmt.pix.height * 2;
  762.             bytesperline = f->fmt.pix.width * 2;
  763.             break;
  764.         case V4L2_PIX_FMT_BGR24:
  765.             size = f->fmt.pix.width * f->fmt.pix.height * 3;
  766.             bytesperline = f->fmt.pix.width * 3;
  767.             break;
  768.         case V4L2_PIX_FMT_RGB24:
  769.             size = f->fmt.pix.width * f->fmt.pix.height * 3;
  770.             bytesperline = f->fmt.pix.width * 3;
  771.             break;
  772.         case V4L2_PIX_FMT_BGR32:
  773.             size = f->fmt.pix.width * f->fmt.pix.height * 4;
  774.             bytesperline = f->fmt.pix.width * 4;
  775.             break;
  776.         case V4L2_PIX_FMT_RGB32:
  777.             size = f->fmt.pix.width * f->fmt.pix.height * 4;
  778.             bytesperline = f->fmt.pix.width * 4;
  779.             break;
  780.         case V4L2_PIX_FMT_YUV422P:
  781.             size = f->fmt.pix.width * f->fmt.pix.height * 2;
  782.             bytesperline = f->fmt.pix.width;
  783.             break;
  784.         case V4L2_PIX_FMT_UYVY:
  785.         case V4L2_PIX_FMT_YUYV:
  786.             size = f->fmt.pix.width * f->fmt.pix.height * 2;
  787.             bytesperline = f->fmt.pix.width * 2;
  788.             break;
  789.         case V4L2_PIX_FMT_YUV420:
  790.             size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2;
  791.             bytesperline = f->fmt.pix.width;
  792.             break;
  793.         case V4L2_PIX_FMT_NV12:
  794.             size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2;
  795.             bytesperline = f->fmt.pix.width;
  796.             break;
  797.         default:
  798.             break;
  799.         }
  800.  
  801.         if (f->fmt.pix.bytesperline < bytesperline) {
  802.             f->fmt.pix.bytesperline = bytesperline;
  803.         } else {
  804.             bytesperline = f->fmt.pix.bytesperline;
  805.         }
  806.  
  807.         if (f->fmt.pix.sizeimage < size) {
  808.             f->fmt.pix.sizeimage = size;
  809.         } else {
  810.             size = f->fmt.pix.sizeimage;
  811.         }
  812.  
  813.         cam->v2f.fmt.pix = f->fmt.pix;
  814.  
  815.         if (cam->v2f.fmt.pix.priv != 0) {
  816.             if (copy_from_user(&cam->offset,
  817.                        (void *)cam->v2f.fmt.pix.priv,
  818.                        sizeof(cam->offset))) {
  819.                 retval = -EFAULT;
  820.                 break;
  821.             }
  822.         }
  823.         break;
  824.     case V4L2_BUF_TYPE_VIDEO_OVERLAY:
  825.         pr_debug("   type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
  826.         retval = verify_preview(cam, &f->fmt.win);
  827.         cam->win = f->fmt.win;
  828.         break;
  829.     default:
  830.         retval = -EINVAL;
  831.     }
  832.  
  833.     pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
  834.          __func__,
  835.          cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
  836.     pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
  837.          __func__,
  838.          cam->crop_bounds.width, cam->crop_bounds.height);
  839.     pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
  840.          __func__,
  841.          cam->crop_defrect.width, cam->crop_defrect.height);
  842.     pr_debug("End of %s: crop_current widthxheight %d x %d\n",
  843.          __func__,
  844.          cam->crop_current.width, cam->crop_current.height);
  845.  
  846.     return retval;
  847. }
  848.  
  849. /*!
  850.  * get control param
  851.  *
  852.  * @param cam         structure cam_data *
  853.  *
  854.  * @param c           structure v4l2_control *
  855.  *
  856.  * @return  status    0 success, EINVAL failed
  857.  */
  858. static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
  859. {
  860.     int status = 0;
  861.  
  862.     pr_debug("In MVC:mxc_v4l2_g_ctrl\n");
  863.  
  864.     /* probably don't need to store the values that can be retrieved,
  865.      * locally, but they are for now. */
  866.     switch (c->id) {
  867.     case V4L2_CID_HFLIP:
  868.         /* This is handled in the ipu. */
  869.         if (cam->rotation == IPU_ROTATE_HORIZ_FLIP)
  870.             c->value = 1;
  871.         break;
  872.     case V4L2_CID_VFLIP:
  873.         /* This is handled in the ipu. */
  874.         if (cam->rotation == IPU_ROTATE_VERT_FLIP)
  875.             c->value = 1;
  876.         break;
  877.     case V4L2_CID_MXC_ROT:
  878.         /* This is handled in the ipu. */
  879.         c->value = cam->rotation;
  880.         break;
  881.     case V4L2_CID_BRIGHTNESS:
  882.         if (cam->sensor) {
  883.             c->value = cam->bright;
  884.             status = vidioc_int_g_ctrl(cam->sensor, c);
  885.             cam->bright = c->value;
  886.         } else {
  887.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  888.             status = -ENODEV;
  889.         }
  890.         break;
  891.     case V4L2_CID_HUE:
  892.         if (cam->sensor) {
  893.             c->value = cam->hue;
  894.             status = vidioc_int_g_ctrl(cam->sensor, c);
  895.             cam->hue = c->value;
  896.         } else {
  897.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  898.             status = -ENODEV;
  899.         }
  900.         break;
  901.     case V4L2_CID_CONTRAST:
  902.         if (cam->sensor) {
  903.             c->value = cam->contrast;
  904.             status = vidioc_int_g_ctrl(cam->sensor, c);
  905.             cam->contrast = c->value;
  906.         } else {
  907.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  908.             status = -ENODEV;
  909.         }
  910.         break;
  911.     case V4L2_CID_SATURATION:
  912.         if (cam->sensor) {
  913.             c->value = cam->saturation;
  914.             status = vidioc_int_g_ctrl(cam->sensor, c);
  915.             cam->saturation = c->value;
  916.         } else {
  917.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  918.             status = -ENODEV;
  919.         }
  920.         break;
  921.     case V4L2_CID_RED_BALANCE:
  922.         if (cam->sensor) {
  923.             c->value = cam->red;
  924.             status = vidioc_int_g_ctrl(cam->sensor, c);
  925.             cam->red = c->value;
  926.         } else {
  927.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  928.             status = -ENODEV;
  929.         }
  930.         break;
  931.     case V4L2_CID_BLUE_BALANCE:
  932.         if (cam->sensor) {
  933.             c->value = cam->blue;
  934.             status = vidioc_int_g_ctrl(cam->sensor, c);
  935.             cam->blue = c->value;
  936.         } else {
  937.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  938.             status = -ENODEV;
  939.         }
  940.         break;
  941.     case V4L2_CID_BLACK_LEVEL:
  942.         if (cam->sensor) {
  943.             c->value = cam->ae_mode;
  944.             status = vidioc_int_g_ctrl(cam->sensor, c);
  945.             cam->ae_mode = c->value;
  946.         } else {
  947.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  948.             status = -ENODEV;
  949.         }
  950.         break;
  951.     default:
  952.         pr_err("ERROR: v4l2 capture: unsupported ioctrl!\n");
  953.     }
  954.  
  955.     return status;
  956. }
  957.  
  958. /*!
  959.  * V4L2 - set_control function
  960.  *          V4L2_CID_PRIVATE_BASE is the extention for IPU preprocessing.
  961.  *          0 for normal operation
  962.  *          1 for vertical flip
  963.  *          2 for horizontal flip
  964.  *          3 for horizontal and vertical flip
  965.  *          4 for 90 degree rotation
  966.  * @param cam         structure cam_data *
  967.  *
  968.  * @param c           structure v4l2_control *
  969.  *
  970.  * @return  status    0 success, EINVAL failed
  971.  */
  972. static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
  973. {
  974.     int ret = 0;
  975.     int tmp_rotation = IPU_ROTATE_NONE;
  976.  
  977.     pr_debug("In MVC:mxc_v4l2_s_ctrl\n");
  978.  
  979.     switch (c->id) {
  980.     case V4L2_CID_HFLIP:
  981.         /* This is done by the IPU */
  982.         if (c->value == 1) {
  983.             if ((cam->rotation != IPU_ROTATE_VERT_FLIP) &&
  984.                 (cam->rotation != IPU_ROTATE_180))
  985.                 cam->rotation = IPU_ROTATE_HORIZ_FLIP;
  986.             else
  987.                 cam->rotation = IPU_ROTATE_180;
  988.         } else {
  989.             if (cam->rotation == IPU_ROTATE_HORIZ_FLIP)
  990.                 cam->rotation = IPU_ROTATE_NONE;
  991.             if (cam->rotation == IPU_ROTATE_180)
  992.                 cam->rotation = IPU_ROTATE_VERT_FLIP;
  993.         }
  994.         break;
  995.     case V4L2_CID_VFLIP:
  996.         /* This is done by the IPU */
  997.         if (c->value == 1) {
  998.             if ((cam->rotation != IPU_ROTATE_HORIZ_FLIP) &&
  999.                 (cam->rotation != IPU_ROTATE_180))
  1000.                 cam->rotation = IPU_ROTATE_VERT_FLIP;
  1001.             else
  1002.                 cam->rotation = IPU_ROTATE_180;
  1003.         } else {
  1004.             if (cam->rotation == IPU_ROTATE_VERT_FLIP)
  1005.                 cam->rotation = IPU_ROTATE_NONE;
  1006.             if (cam->rotation == IPU_ROTATE_180)
  1007.                 cam->rotation = IPU_ROTATE_HORIZ_FLIP;
  1008.         }
  1009.         break;
  1010.     case V4L2_CID_MXC_ROT:
  1011.     case V4L2_CID_MXC_VF_ROT:
  1012.         /* This is done by the IPU */
  1013.         switch (c->value) {
  1014.         case V4L2_MXC_ROTATE_NONE:
  1015.             tmp_rotation = IPU_ROTATE_NONE;
  1016.             break;
  1017.         case V4L2_MXC_ROTATE_VERT_FLIP:
  1018.             tmp_rotation = IPU_ROTATE_VERT_FLIP;
  1019.             break;
  1020.         case V4L2_MXC_ROTATE_HORIZ_FLIP:
  1021.             tmp_rotation = IPU_ROTATE_HORIZ_FLIP;
  1022.             break;
  1023.         case V4L2_MXC_ROTATE_180:
  1024.             tmp_rotation = IPU_ROTATE_180;
  1025.             break;
  1026.         case V4L2_MXC_ROTATE_90_RIGHT:
  1027.             tmp_rotation = IPU_ROTATE_90_RIGHT;
  1028.             break;
  1029.         case V4L2_MXC_ROTATE_90_RIGHT_VFLIP:
  1030.             tmp_rotation = IPU_ROTATE_90_RIGHT_VFLIP;
  1031.             break;
  1032.         case V4L2_MXC_ROTATE_90_RIGHT_HFLIP:
  1033.             tmp_rotation = IPU_ROTATE_90_RIGHT_HFLIP;
  1034.             break;
  1035.         case V4L2_MXC_ROTATE_90_LEFT:
  1036.             tmp_rotation = IPU_ROTATE_90_LEFT;
  1037.             break;
  1038.         case V4L2_MXC_CAM_ROTATE_NONE:
  1039.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1040.                     true, true);
  1041.             if (vidioc_int_s_ctrl(cam->sensor, c)) {
  1042.                 ret = -EINVAL;
  1043.             }
  1044.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1045.                     false, false);
  1046.             break;
  1047.         case V4L2_MXC_CAM_ROTATE_VERT_FLIP:
  1048.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1049.                     true, true);
  1050.             if (vidioc_int_s_ctrl(cam->sensor, c)) {
  1051.                 ret = -EINVAL;
  1052.             }
  1053.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1054.                     false, false);
  1055.             break;
  1056.         case V4L2_MXC_CAM_ROTATE_HORIZ_FLIP:
  1057.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1058.                     true, true);
  1059.             if (vidioc_int_s_ctrl(cam->sensor, c)) {
  1060.                 ret = -EINVAL;
  1061.             }
  1062.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1063.                     false, false);
  1064.             break;
  1065.         case V4L2_MXC_CAM_ROTATE_180:
  1066.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1067.                     true, true);
  1068.             if (vidioc_int_s_ctrl(cam->sensor, c)) {
  1069.                 ret = -EINVAL;
  1070.             }
  1071.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1072.                     false, false);
  1073.             break;
  1074.         default:
  1075.             ret = -EINVAL;
  1076.         }
  1077.  
  1078.         if (c->id == V4L2_CID_MXC_VF_ROT)
  1079.             cam->vf_rotation = tmp_rotation;
  1080.         else
  1081.             cam->rotation = tmp_rotation;
  1082.  
  1083.         break;
  1084.     case V4L2_CID_HUE:
  1085.         if (cam->sensor) {
  1086.             cam->hue = c->value;
  1087.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1088.                            true, true);
  1089.             ret = vidioc_int_s_ctrl(cam->sensor, c);
  1090.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1091.                            false, false);
  1092.         } else {
  1093.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  1094.             ret = -ENODEV;
  1095.         }
  1096.         break;
  1097.     case V4L2_CID_CONTRAST:
  1098.         if (cam->sensor) {
  1099.             cam->contrast = c->value;
  1100.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1101.                            true, true);
  1102.             ret = vidioc_int_s_ctrl(cam->sensor, c);
  1103.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1104.                            false, false);
  1105.         } else {
  1106.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  1107.             ret = -ENODEV;
  1108.         }
  1109.         break;
  1110.     case V4L2_CID_BRIGHTNESS:
  1111.         if (cam->sensor) {
  1112.             cam->bright = c->value;
  1113.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1114.                            true, true);
  1115.             ret = vidioc_int_s_ctrl(cam->sensor, c);
  1116.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1117.                            false, false);
  1118.         } else {
  1119.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  1120.             ret = -ENODEV;
  1121.         }
  1122.         break;
  1123.     case V4L2_CID_SATURATION:
  1124.         if (cam->sensor) {
  1125.             cam->saturation = c->value;
  1126.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1127.                            true, true);
  1128.             ret = vidioc_int_s_ctrl(cam->sensor, c);
  1129.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1130.                            false, false);
  1131.         } else {
  1132.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  1133.             ret = -ENODEV;
  1134.         }
  1135.         break;
  1136.     case V4L2_CID_RED_BALANCE:
  1137.         if (cam->sensor) {
  1138.             cam->red = c->value;
  1139.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1140.                            true, true);
  1141.             ret = vidioc_int_s_ctrl(cam->sensor, c);
  1142.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1143.                            false, false);
  1144.         } else {
  1145.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  1146.             ret = -ENODEV;
  1147.         }
  1148.         break;
  1149.     case V4L2_CID_BLUE_BALANCE:
  1150.         if (cam->sensor) {
  1151.             cam->blue = c->value;
  1152.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1153.                            true, true);
  1154.             ret = vidioc_int_s_ctrl(cam->sensor, c);
  1155.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1156.                            false, false);
  1157.         } else {
  1158.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  1159.             ret = -ENODEV;
  1160.         }
  1161.         break;
  1162.     case V4L2_CID_EXPOSURE:
  1163.         if (cam->sensor) {
  1164.             cam->ae_mode = c->value;
  1165.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1166.                            true, true);
  1167.             ret = vidioc_int_s_ctrl(cam->sensor, c);
  1168.             ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1169.                            false, false);
  1170.         } else {
  1171.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  1172.             ret = -ENODEV;
  1173.         }
  1174.         break;
  1175.     case V4L2_CID_MXC_FLASH:
  1176. #ifdef CONFIG_MXC_IPU_V1
  1177.         ipu_csi_flash_strobe(true);
  1178. #endif
  1179.         break;
  1180.     default:
  1181.         pr_debug("   default case\n");
  1182.         ret = -EINVAL;
  1183.         break;
  1184.     }
  1185.  
  1186.     return ret;
  1187. }
  1188.  
  1189. /*!
  1190.  * V4L2 - mxc_v4l2_s_param function
  1191.  * Allows setting of capturemode and frame rate.
  1192.  *
  1193.  * @param cam         structure cam_data *
  1194.  * @param parm        structure v4l2_streamparm *
  1195.  *
  1196.  * @return  status    0 success, EINVAL failed
  1197.  */
  1198. static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
  1199. {
  1200.     struct v4l2_ifparm ifparm;
  1201.     struct v4l2_format cam_fmt;
  1202.     struct v4l2_streamparm currentparm;
  1203.     ipu_csi_signal_cfg_t csi_param;
  1204.     int err = 0;
  1205.  
  1206.     pr_debug("In mxc_v4l2_s_param\n");
  1207.  
  1208.     if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
  1209.         pr_err(KERN_ERR "mxc_v4l2_s_param invalid type\n");
  1210.         return -EINVAL;
  1211.     }
  1212.  
  1213.     /* Stop the viewfinder */
  1214.     if (cam->overlay_on == true) {
  1215.         stop_preview(cam);
  1216.     }
  1217.  
  1218.     currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1219.  
  1220.     /* First check that this device can support the changes requested. */
  1221.     err = vidioc_int_g_parm(cam->sensor, &currentparm);
  1222.     if (err) {
  1223.         pr_err("%s: vidioc_int_g_parm returned an error %d\n",
  1224.             __func__, err);
  1225.         goto exit;
  1226.     }
  1227.  
  1228.     pr_debug("   Current capabilities are %x\n",
  1229.             currentparm.parm.capture.capability);
  1230.     pr_debug("   Current capturemode is %d  change to %d\n",
  1231.             currentparm.parm.capture.capturemode,
  1232.             parm->parm.capture.capturemode);
  1233.     pr_debug("   Current framerate is %d  change to %d\n",
  1234.             currentparm.parm.capture.timeperframe.denominator,
  1235.             parm->parm.capture.timeperframe.denominator);
  1236.  
  1237.     /* This will change any camera settings needed. */
  1238.     ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, true, true);
  1239.     err = vidioc_int_s_parm(cam->sensor, parm);
  1240.     ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, false, false);
  1241.     if (err) {
  1242.         pr_err("%s: vidioc_int_s_parm returned an error %d\n",
  1243.             __func__, err);
  1244.         goto exit;
  1245.     }
  1246.  
  1247.     /* If resolution changed, need to re-program the CSI */
  1248.     /* Get new values. */
  1249.     vidioc_int_g_ifparm(cam->sensor, &ifparm);
  1250.  
  1251.     csi_param.data_width = 0;
  1252.     csi_param.clk_mode = 0;
  1253.     csi_param.ext_vsync = 0;
  1254.     csi_param.Vsync_pol = 0;
  1255.     csi_param.Hsync_pol = 0;
  1256.     csi_param.pixclk_pol = 0;
  1257.     csi_param.data_pol = 0;
  1258.     csi_param.sens_clksrc = 0;
  1259.     csi_param.pack_tight = 0;
  1260.     csi_param.force_eof = 0;
  1261.     csi_param.data_en_pol = 0;
  1262.     csi_param.data_fmt = 0;
  1263.     csi_param.csi = 0;
  1264.     csi_param.mclk = 0;
  1265.  
  1266.     /* This may not work on other platforms. Check when adding a new one.*/
  1267.     pr_debug("   clock_curr=mclk=%d\n", ifparm.u.bt656.clock_curr);
  1268.     if (ifparm.u.bt656.clock_curr == 0) {
  1269.         csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
  1270.     } else {
  1271.         csi_param.clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
  1272.     }
  1273.  
  1274.     csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv;
  1275.  
  1276.     if (ifparm.u.bt656.mode == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT) {
  1277.         csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
  1278.     } else if (ifparm.u.bt656.mode
  1279.                 == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT) {
  1280.         csi_param.data_width = IPU_CSI_DATA_WIDTH_10;
  1281.     } else {
  1282.         csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
  1283.     }
  1284.  
  1285.     csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv;
  1286.     csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv;
  1287.     csi_param.ext_vsync = ifparm.u.bt656.bt_sync_correct;
  1288.  
  1289.     /* if the capturemode changed, the size bounds will have changed. */
  1290.     cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1291.     vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
  1292.     pr_debug("   g_fmt_cap returns widthxheight of input as %d x %d\n",
  1293.             cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height);
  1294.  
  1295.     csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat;
  1296.  
  1297.     cam->crop_bounds.top = cam->crop_bounds.left = 0;
  1298.     cam->crop_bounds.width = cam_fmt.fmt.pix.width;
  1299.     cam->crop_bounds.height = cam_fmt.fmt.pix.height;
  1300.  
  1301.     /*
  1302.      * Set the default current cropped resolution to be the same with
  1303.      * the cropping boundary(except for tvin module).
  1304.      */
  1305.     if (cam->device_type != 1) {
  1306.         cam->crop_current.width = cam->crop_bounds.width;
  1307.         cam->crop_current.height = cam->crop_bounds.height;
  1308.     }
  1309.  
  1310.     /* This essentially loses the data at the left and bottom of the image
  1311.      * giving a digital zoom image, if crop_current is less than the full
  1312.      * size of the image. */
  1313.     ipu_csi_set_window_size(cam->crop_current.width,
  1314.                 cam->crop_current.height, cam->csi);
  1315.     ipu_csi_set_window_pos(cam->crop_current.left,
  1316.                    cam->crop_current.top,
  1317.                    cam->csi);
  1318.     ipu_csi_init_interface(cam->crop_bounds.width,
  1319.                    cam->crop_bounds.height,
  1320.                    cam_fmt.fmt.pix.pixelformat, csi_param);
  1321.  
  1322.  
  1323. exit:
  1324.     if (cam->overlay_on == true)
  1325.         start_preview(cam);
  1326.  
  1327.     return err;
  1328. }
  1329.  
  1330. /*!
  1331.  * V4L2 - mxc_v4l2_s_std function
  1332.  *
  1333.  * Sets the TV standard to be used.
  1334.  *
  1335.  * @param cam         structure cam_data *
  1336.  * @param parm        structure v4l2_streamparm *
  1337.  *
  1338.  * @return  status    0 success, EINVAL failed
  1339.  */
  1340. static int mxc_v4l2_s_std(cam_data *cam, v4l2_std_id e)
  1341. {
  1342.     pr_debug("In mxc_v4l2_s_std %Lx\n", e);
  1343.     if (e == V4L2_STD_PAL) {
  1344.         pr_debug("   Setting standard to PAL %Lx\n", V4L2_STD_PAL);
  1345.         cam->standard.id = V4L2_STD_PAL;
  1346.         video_index = TV_PAL;
  1347.     } else if (e == V4L2_STD_NTSC) {
  1348.         pr_debug("   Setting standard to NTSC %Lx\n",
  1349.                 V4L2_STD_NTSC);
  1350.         /* Get rid of the white dot line in NTSC signal input */
  1351.         cam->standard.id = V4L2_STD_NTSC;
  1352.         video_index = TV_NTSC;
  1353.     } else {
  1354.         cam->standard.id = V4L2_STD_ALL;
  1355.         video_index = TV_NOT_LOCKED;
  1356.         pr_err("ERROR: unrecognized std! %Lx (PAL=%Lx, NTSC=%Lx\n",
  1357.             e, V4L2_STD_PAL, V4L2_STD_NTSC);
  1358.     }
  1359.  
  1360.     cam->standard.index = video_index;
  1361.     strcpy(cam->standard.name, video_fmts[video_index].name);
  1362.     cam->crop_bounds.width = video_fmts[video_index].raw_width;
  1363.     cam->crop_bounds.height = video_fmts[video_index].raw_height;
  1364.     cam->crop_current.width = video_fmts[video_index].active_width;
  1365.     cam->crop_current.height = video_fmts[video_index].active_height;
  1366.     cam->crop_current.top = video_fmts[video_index].active_top;
  1367.     cam->crop_current.left = video_fmts[video_index].active_left;
  1368.  
  1369.     return 0;
  1370. }
  1371.  
  1372. /*!
  1373.  * V4L2 - mxc_v4l2_g_std function
  1374.  *
  1375.  * Gets the TV standard from the TV input device.
  1376.  *
  1377.  * @param cam         structure cam_data *
  1378.  *
  1379.  * @param e       structure v4l2_streamparm *
  1380.  *
  1381.  * @return  status    0 success, EINVAL failed
  1382.  */
  1383. static int mxc_v4l2_g_std(cam_data *cam, v4l2_std_id *e)
  1384. {
  1385.     struct v4l2_format tv_fmt;
  1386.  
  1387.     pr_debug("In mxc_v4l2_g_std\n");
  1388.  
  1389.     if (cam->device_type == 1) {
  1390.         /* Use this function to get what the TV-In device detects the
  1391.          * format to be. pixelformat is used to return the std value
  1392.          * since the interface has no vidioc_g_std.*/
  1393.         tv_fmt.type = V4L2_BUF_TYPE_PRIVATE;
  1394.         vidioc_int_g_fmt_cap(cam->sensor, &tv_fmt);
  1395.  
  1396.         /* If the TV-in automatically detects the standard, then if it
  1397.          * changes, the settings need to change. */
  1398.         if (cam->standard_autodetect) {
  1399.             if (cam->standard.id != tv_fmt.fmt.pix.pixelformat) {
  1400.                 pr_debug("MVC: mxc_v4l2_g_std: "
  1401.                     "Changing standard\n");
  1402.                 mxc_v4l2_s_std(cam, tv_fmt.fmt.pix.pixelformat);
  1403.             }
  1404.         }
  1405.  
  1406.         *e = tv_fmt.fmt.pix.pixelformat;
  1407.     }
  1408.  
  1409.     return 0;
  1410. }
  1411.  
  1412. /*!
  1413.  * Dequeue one V4L capture buffer
  1414.  *
  1415.  * @param cam         structure cam_data *
  1416.  * @param buf         structure v4l2_buffer *
  1417.  *
  1418.  * @return  status    0 success, EINVAL invalid frame number,
  1419.  *                    ETIME timeout, ERESTARTSYS interrupted by user
  1420.  */
  1421. static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
  1422. {
  1423.     int retval = 0;
  1424.     struct mxc_v4l_frame *frame;
  1425.     unsigned long lock_flags;
  1426.  
  1427.     pr_debug("In MVC:mxc_v4l_dqueue\n");
  1428.  
  1429.     if (!wait_event_interruptible_timeout(cam->enc_queue,
  1430.                           cam->enc_counter != 0, 10 * HZ)) {
  1431.         pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout "
  1432.             "enc_counter %x\n",
  1433.                cam->enc_counter);
  1434.         return -ETIME;
  1435.     } else if (signal_pending(current)) {
  1436.         pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() "
  1437.             "interrupt received\n");
  1438.         return -ERESTARTSYS;
  1439.     }
  1440.  
  1441.     spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags);
  1442.  
  1443.     cam->enc_counter--;
  1444.  
  1445.     frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue);
  1446.     list_del(cam->done_q.next);
  1447.     if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) {
  1448.         frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE;
  1449.     } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {
  1450.         pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: "
  1451.             "Buffer not filled.\n");
  1452.         frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;
  1453.         retval = -EINVAL;
  1454.     } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) {
  1455.         pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: "
  1456.             "Buffer not queued.\n");
  1457.         retval = -EINVAL;
  1458.     }
  1459.  
  1460.     buf->bytesused = cam->v2f.fmt.pix.sizeimage;
  1461.     buf->index = frame->index;
  1462.     buf->flags = frame->buffer.flags;
  1463.     buf->m = cam->frame[frame->index].buffer.m;
  1464.     buf->timestamp = cam->frame[frame->index].buffer.timestamp;
  1465.  
  1466.     spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags);
  1467.     return retval;
  1468. }
  1469.  
  1470. /*!
  1471.  * V4L interface - open function
  1472.  *
  1473.  * @param file         structure file *
  1474.  *
  1475.  * @return  status    0 success, ENODEV invalid device instance,
  1476.  *                    ENODEV timeout, ERESTARTSYS interrupted by user
  1477.  */
  1478. static int mxc_v4l_open(struct file *file)
  1479. {
  1480.     struct v4l2_ifparm ifparm;
  1481.     struct v4l2_format cam_fmt;
  1482.     ipu_csi_signal_cfg_t csi_param;
  1483.     struct video_device *dev = video_devdata(file);
  1484.     cam_data *cam = video_get_drvdata(dev);
  1485.     int err = 0;
  1486.  
  1487.     pr_debug("\nIn MVC: mxc_v4l_open\n");
  1488.     pr_debug("   device name is %s\n", dev->name);
  1489.  
  1490.     if (!cam) {
  1491.         pr_err("ERROR: v4l2 capture: Internal error, "
  1492.             "cam_data not found!\n");
  1493.         return -EBADF;
  1494.     }
  1495.  
  1496.     if (cam->sensor == NULL ||
  1497.         cam->sensor->type != v4l2_int_type_slave) {
  1498.         pr_err("ERROR: v4l2 capture: slave not found!\n");
  1499.         return -EAGAIN;
  1500.     }
  1501.  
  1502.     down(&cam->busy_lock);
  1503.     err = 0;
  1504.     if (signal_pending(current))
  1505.         goto oops;
  1506.  
  1507.     if (cam->open_count++ == 0) {
  1508.         wait_event_interruptible(cam->power_queue,
  1509.                      cam->low_power == false);
  1510.  
  1511.         if (strcmp(mxc_capture_inputs[cam->current_input].name,
  1512.                "CSI MEM") == 0) {
  1513. #if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
  1514.             err = csi_enc_select(cam);
  1515. #endif
  1516.         } else if (strcmp(mxc_capture_inputs[cam->current_input].name,
  1517.                   "CSI IC MEM") == 0) {
  1518. #if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
  1519.             err = prp_enc_select(cam);
  1520. #endif
  1521.         }
  1522.  
  1523.         cam->enc_counter = 0;
  1524.         INIT_LIST_HEAD(&cam->ready_q);
  1525.         INIT_LIST_HEAD(&cam->working_q);
  1526.         INIT_LIST_HEAD(&cam->done_q);
  1527.  
  1528.         vidioc_int_g_ifparm(cam->sensor, &ifparm);
  1529.  
  1530.         csi_param.sens_clksrc = 0;
  1531.  
  1532.         csi_param.clk_mode = 0;
  1533.         csi_param.data_pol = 0;
  1534.         csi_param.ext_vsync = 0;
  1535.  
  1536.         csi_param.pack_tight = 0;
  1537.         csi_param.force_eof = 0;
  1538.         csi_param.data_en_pol = 0;
  1539.         csi_param.mclk = ifparm.u.bt656.clock_curr;
  1540.  
  1541.         csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv;
  1542.  
  1543.         /* Once we handle multiple inputs this will need to change. */
  1544.         csi_param.csi = 0;
  1545.  
  1546.         if (ifparm.u.bt656.mode
  1547.                 == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT)
  1548.             csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
  1549.         else if (ifparm.u.bt656.mode
  1550.                 == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT)
  1551.             csi_param.data_width = IPU_CSI_DATA_WIDTH_10;
  1552.         else
  1553.             csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
  1554.  
  1555.  
  1556.         csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv;
  1557.         csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv;
  1558.  
  1559.         csi_param.csi = cam->csi;
  1560.  
  1561.         cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1562.         vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
  1563.  
  1564.         /* Reset the sizes.  Needed to prevent carryover of last
  1565.          * operation.*/
  1566.         cam->crop_bounds.top = cam->crop_bounds.left = 0;
  1567.         cam->crop_bounds.width = cam_fmt.fmt.pix.width;
  1568.         cam->crop_bounds.height = cam_fmt.fmt.pix.height;
  1569.  
  1570.         /* This also is the max crop size for this device. */
  1571.         cam->crop_defrect.top = cam->crop_defrect.left = 0;
  1572.         cam->crop_defrect.width = cam_fmt.fmt.pix.width;
  1573.         cam->crop_defrect.height = cam_fmt.fmt.pix.height;
  1574.  
  1575.         /* At this point, this is also the current image size. */
  1576.         cam->crop_current.top = cam->crop_current.left = 0;
  1577.         cam->crop_current.width = cam_fmt.fmt.pix.width;
  1578.         cam->crop_current.height = cam_fmt.fmt.pix.height;
  1579.  
  1580.         pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
  1581.             __func__,
  1582.             cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
  1583.         pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
  1584.             __func__,
  1585.             cam->crop_bounds.width, cam->crop_bounds.height);
  1586.         pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
  1587.             __func__,
  1588.             cam->crop_defrect.width, cam->crop_defrect.height);
  1589.         pr_debug("End of %s: crop_current widthxheight %d x %d\n",
  1590.             __func__,
  1591.             cam->crop_current.width, cam->crop_current.height);
  1592.  
  1593.         csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat;
  1594.         pr_debug("On Open: Input to ipu size is %d x %d\n",
  1595.                 cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height);
  1596.         ipu_csi_set_window_size(cam->crop_current.width,
  1597.                     cam->crop_current.height,
  1598.                     cam->csi);
  1599.         ipu_csi_set_window_pos(cam->crop_current.left,
  1600.                     cam->crop_current.top,
  1601.                     cam->csi);
  1602.         ipu_csi_init_interface(cam->crop_bounds.width,
  1603.                     cam->crop_bounds.height,
  1604.                     cam_fmt.fmt.pix.pixelformat,
  1605.                     csi_param);
  1606.  
  1607.         ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1608.                        true, true);
  1609.         vidioc_int_init(cam->sensor);
  1610.  
  1611.         ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
  1612.                        false, false);
  1613. }
  1614.  
  1615.     file->private_data = dev;
  1616.  
  1617.       oops:
  1618.     up(&cam->busy_lock);
  1619.     return err;
  1620. }
  1621.  
  1622. /*!
  1623.  * V4L interface - close function
  1624.  *
  1625.  * @param file     struct file *
  1626.  *
  1627.  * @return         0 success
  1628.  */
  1629. static int mxc_v4l_close(struct file *file)
  1630. {
  1631.     struct video_device *dev = video_devdata(file);
  1632.     int err = 0;
  1633.     cam_data *cam = video_get_drvdata(dev);
  1634.  
  1635.     pr_debug("In MVC:mxc_v4l_close\n");
  1636.  
  1637.     if (!cam) {
  1638.         pr_err("ERROR: v4l2 capture: Internal error, "
  1639.             "cam_data not found!\n");
  1640.         return -EBADF;
  1641.     }
  1642.  
  1643.     /* for the case somebody hit the ctrl C */
  1644.     if (cam->overlay_pid == current->pid) {
  1645.         err = stop_preview(cam);
  1646.         cam->overlay_on = false;
  1647.     }
  1648.     if (cam->capture_pid == current->pid) {
  1649.         err |= mxc_streamoff(cam);
  1650.         wake_up_interruptible(&cam->enc_queue);
  1651.     }
  1652.  
  1653.     if (--cam->open_count == 0) {
  1654.         wait_event_interruptible(cam->power_queue,
  1655.                      cam->low_power == false);
  1656.         pr_info("mxc_v4l_close: release resource\n");
  1657.  
  1658.         if (strcmp(mxc_capture_inputs[cam->current_input].name,
  1659.                "CSI MEM") == 0) {
  1660. #if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
  1661.             err |= csi_enc_deselect(cam);
  1662. #endif
  1663.         } else if (strcmp(mxc_capture_inputs[cam->current_input].name,
  1664.                   "CSI IC MEM") == 0) {
  1665. #if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
  1666.             err |= prp_enc_deselect(cam);
  1667. #endif
  1668.         }
  1669.  
  1670.         mxc_free_frame_buf(cam);
  1671.         file->private_data = NULL;
  1672.  
  1673.         /* capture off */
  1674.         wake_up_interruptible(&cam->enc_queue);
  1675.         mxc_free_frames(cam);
  1676.         cam->enc_counter++;
  1677.     }
  1678.  
  1679.     return err;
  1680. }
  1681.  
  1682. #if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC) || \
  1683.     defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) || \
  1684.     defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
  1685. /*
  1686.  * V4L interface - read function
  1687.  *
  1688.  * @param file       struct file *
  1689.  * @param read buf   char *
  1690.  * @param count      size_t
  1691.  * @param ppos       structure loff_t *
  1692.  *
  1693.  * @return           bytes read
  1694.  */
  1695. static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count,
  1696.                 loff_t *ppos)
  1697. {
  1698.     int err = 0;
  1699.     u8 *v_address[2];
  1700.     struct video_device *dev = video_devdata(file);
  1701.     cam_data *cam = video_get_drvdata(dev);
  1702.  
  1703.     if (down_interruptible(&cam->busy_lock))
  1704.         return -EINTR;
  1705.  
  1706.     /* Stop the viewfinder */
  1707.     if (cam->overlay_on == true)
  1708.         stop_preview(cam);
  1709.  
  1710.     v_address[0] = dma_alloc_coherent(0,
  1711.                        PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
  1712.                        &cam->still_buf[0],
  1713.                        GFP_DMA | GFP_KERNEL);
  1714.  
  1715.     v_address[1] = dma_alloc_coherent(0,
  1716.                        PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
  1717.                        &cam->still_buf[1],
  1718.                        GFP_DMA | GFP_KERNEL);
  1719.  
  1720.     if (!v_address[0] || !v_address[1]) {
  1721.         err = -ENOBUFS;
  1722.         goto exit0;
  1723.     }
  1724.  
  1725.     err = prp_still_select(cam);
  1726.     if (err != 0) {
  1727.         err = -EIO;
  1728.         goto exit0;
  1729.     }
  1730.  
  1731.     cam->still_counter = 0;
  1732.     err = cam->csi_start(cam);
  1733.     if (err != 0) {
  1734.         err = -EIO;
  1735.         goto exit1;
  1736.     }
  1737.  
  1738.     if (!wait_event_interruptible_timeout(cam->still_queue,
  1739.                           cam->still_counter != 0,
  1740.                           10 * HZ)) {
  1741.         pr_err("ERROR: v4l2 capture: mxc_v4l_read timeout counter %x\n",
  1742.                cam->still_counter);
  1743.         err = -ETIME;
  1744.         goto exit1;
  1745.     }
  1746.     err = copy_to_user(buf, v_address[1], cam->v2f.fmt.pix.sizeimage);
  1747.  
  1748.       exit1:
  1749.     prp_still_deselect(cam);
  1750.  
  1751.       exit0:
  1752.     if (v_address[0] != 0)
  1753.         dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[0],
  1754.                   cam->still_buf[0]);
  1755.     if (v_address[1] != 0)
  1756.         dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[1],
  1757.                   cam->still_buf[1]);
  1758.  
  1759.     cam->still_buf[0] = cam->still_buf[1] = 0;
  1760.  
  1761.     if (cam->overlay_on == true) {
  1762.         start_preview(cam);
  1763.     }
  1764.  
  1765.     up(&cam->busy_lock);
  1766.     if (err < 0)
  1767.         return err;
  1768.  
  1769.     return cam->v2f.fmt.pix.sizeimage - err;
  1770. }
  1771. #endif
  1772.  
  1773. /*!
  1774.  * V4L interface - ioctl function
  1775.  *
  1776.  * @param file       struct file*
  1777.  *
  1778.  * @param ioctlnr    unsigned int
  1779.  *
  1780.  * @param arg        void*
  1781.  *
  1782.  * @return           0 success, ENODEV for invalid device instance,
  1783.  *                   -1 for other errors.
  1784.  */
  1785. static long mxc_v4l_do_ioctl(struct file *file,
  1786.                 unsigned int ioctlnr, void *arg)
  1787. {
  1788.     struct video_device *dev = video_devdata(file);
  1789.     cam_data *cam = video_get_drvdata(dev);
  1790.     int retval = 0;
  1791.     unsigned long lock_flags;
  1792.  
  1793.     pr_debug("In MVC: mxc_v4l_do_ioctl %x\n", ioctlnr);
  1794.     wait_event_interruptible(cam->power_queue, cam->low_power == false);
  1795.     /* make this _really_ smp-safe */
  1796.     if (down_interruptible(&cam->busy_lock))
  1797.         return -EBUSY;
  1798.  
  1799.     switch (ioctlnr) {
  1800.     /*!
  1801.      * V4l2 VIDIOC_QUERYCAP ioctl
  1802.      */
  1803.     case VIDIOC_QUERYCAP: {
  1804.         struct v4l2_capability *cap = arg;
  1805.         pr_debug("   case VIDIOC_QUERYCAP\n");
  1806.         strcpy(cap->driver, "mxc_v4l2");
  1807.         cap->version = KERNEL_VERSION(0, 1, 11);
  1808.         cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
  1809.                     V4L2_CAP_VIDEO_OVERLAY |
  1810.                     V4L2_CAP_STREAMING |
  1811.                     V4L2_CAP_READWRITE;
  1812.         cap->card[0] = '\0';
  1813.         cap->bus_info[0] = '\0';
  1814.         break;
  1815.     }
  1816.  
  1817.     /*!
  1818.      * V4l2 VIDIOC_G_FMT ioctl
  1819.      */
  1820.     case VIDIOC_G_FMT: {
  1821.         struct v4l2_format *gf = arg;
  1822.         pr_debug("   case VIDIOC_G_FMT\n");
  1823.         retval = mxc_v4l2_g_fmt(cam, gf);
  1824.         break;
  1825.     }
  1826.  
  1827.     /*!
  1828.      * V4l2 VIDIOC_S_FMT ioctl
  1829.      */
  1830.     case VIDIOC_S_FMT: {
  1831.         struct v4l2_format *sf = arg;
  1832.         pr_debug("   case VIDIOC_S_FMT\n");
  1833.         retval = mxc_v4l2_s_fmt(cam, sf);
  1834.         break;
  1835.     }
  1836.  
  1837.     /*!
  1838.      * V4l2 VIDIOC_REQBUFS ioctl
  1839.      */
  1840.     case VIDIOC_REQBUFS: {
  1841.         struct v4l2_requestbuffers *req = arg;
  1842.         pr_debug("   case VIDIOC_REQBUFS\n");
  1843.  
  1844.         if (req->count > FRAME_NUM) {
  1845.             pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: "
  1846.                    "not enough buffers\n");
  1847.             req->count = FRAME_NUM;
  1848.         }
  1849.  
  1850.         if ((req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
  1851.             (req->memory != V4L2_MEMORY_MMAP)) {
  1852.             pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: "
  1853.                    "wrong buffer type\n");
  1854.             retval = -EINVAL;
  1855.             break;
  1856.         }
  1857.  
  1858.         mxc_streamoff(cam);
  1859.         mxc_free_frame_buf(cam);
  1860.         cam->enc_counter = 0;
  1861.         INIT_LIST_HEAD(&cam->ready_q);
  1862.         INIT_LIST_HEAD(&cam->working_q);
  1863.         INIT_LIST_HEAD(&cam->done_q);
  1864.  
  1865.         retval = mxc_allocate_frame_buf(cam, req->count);
  1866.         break;
  1867.     }
  1868.  
  1869.     /*!
  1870.      * V4l2 VIDIOC_QUERYBUF ioctl
  1871.      */
  1872.     case VIDIOC_QUERYBUF: {
  1873.         struct v4l2_buffer *buf = arg;
  1874.         int index = buf->index;
  1875.         pr_debug("   case VIDIOC_QUERYBUF\n");
  1876.  
  1877.         if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
  1878.             pr_err("ERROR: v4l2 capture: "
  1879.                    "VIDIOC_QUERYBUFS: "
  1880.                    "wrong buffer type\n");
  1881.             retval = -EINVAL;
  1882.             break;
  1883.         }
  1884.  
  1885.         memset(buf, 0, sizeof(buf));
  1886.         buf->index = index;
  1887.  
  1888.         down(&cam->param_lock);
  1889.         retval = mxc_v4l2_buffer_status(cam, buf);
  1890.         up(&cam->param_lock);
  1891.         break;
  1892.     }
  1893.  
  1894.     /*!
  1895.      * V4l2 VIDIOC_QBUF ioctl
  1896.      */
  1897.     case VIDIOC_QBUF: {
  1898.         struct v4l2_buffer *buf = arg;
  1899.         int index = buf->index;
  1900.         pr_debug("   case VIDIOC_QBUF\n");
  1901.  
  1902.         spin_lock_irqsave(&cam->queue_int_lock, lock_flags);
  1903.         if ((cam->frame[index].buffer.flags & 0x7) ==
  1904.             V4L2_BUF_FLAG_MAPPED) {
  1905.             cam->frame[index].buffer.flags |=
  1906.                 V4L2_BUF_FLAG_QUEUED;
  1907.             list_add_tail(&cam->frame[index].queue,
  1908.                       &cam->ready_q);
  1909.         } else if (cam->frame[index].buffer.
  1910.                flags & V4L2_BUF_FLAG_QUEUED) {
  1911.             pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: "
  1912.                    "buffer already queued\n");
  1913.             retval = -EINVAL;
  1914.         } else if (cam->frame[index].buffer.
  1915.                flags & V4L2_BUF_FLAG_DONE) {
  1916.             pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: "
  1917.                    "overwrite done buffer.\n");
  1918.             cam->frame[index].buffer.flags &=
  1919.                 ~V4L2_BUF_FLAG_DONE;
  1920.             cam->frame[index].buffer.flags |=
  1921.                 V4L2_BUF_FLAG_QUEUED;
  1922.             retval = -EINVAL;
  1923.         }
  1924.  
  1925.         buf->flags = cam->frame[index].buffer.flags;
  1926.         spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
  1927.         break;
  1928.     }
  1929.  
  1930.     /*!
  1931.      * V4l2 VIDIOC_DQBUF ioctl
  1932.      */
  1933.     case VIDIOC_DQBUF: {
  1934.         struct v4l2_buffer *buf = arg;
  1935.         pr_debug("   case VIDIOC_DQBUF\n");
  1936.  
  1937.         if ((cam->enc_counter == 0) &&
  1938.             (file->f_flags & O_NONBLOCK)) {
  1939.             retval = -EAGAIN;
  1940.             break;
  1941.         }
  1942.  
  1943.         retval = mxc_v4l_dqueue(cam, buf);
  1944.  
  1945.         break;
  1946.     }
  1947.  
  1948.     /*!
  1949.      * V4l2 VIDIOC_STREAMON ioctl
  1950.      */
  1951.     case VIDIOC_STREAMON: {
  1952.         pr_debug("   case VIDIOC_STREAMON\n");
  1953.         retval = mxc_streamon(cam);
  1954.         break;
  1955.     }
  1956.  
  1957.     /*!
  1958.      * V4l2 VIDIOC_STREAMOFF ioctl
  1959.      */
  1960.     case VIDIOC_STREAMOFF: {
  1961.         pr_debug("   case VIDIOC_STREAMOFF\n");
  1962.         retval = mxc_streamoff(cam);
  1963.         break;
  1964.     }
  1965.  
  1966.     /*!
  1967.      * V4l2 VIDIOC_G_CTRL ioctl
  1968.      */
  1969.     case VIDIOC_G_CTRL: {
  1970.         pr_debug("   case VIDIOC_G_CTRL\n");
  1971.         retval = mxc_v4l2_g_ctrl(cam, arg);
  1972.         break;
  1973.     }
  1974.  
  1975.     /*!
  1976.      * V4l2 VIDIOC_S_CTRL ioctl
  1977.      */
  1978.     case VIDIOC_S_CTRL: {
  1979.         pr_debug("   case VIDIOC_S_CTRL\n");
  1980.         retval = mxc_v4l2_s_ctrl(cam, arg);
  1981.         break;
  1982.     }
  1983.  
  1984.     /*!
  1985.      * V4l2 VIDIOC_CROPCAP ioctl
  1986.      */
  1987.     case VIDIOC_CROPCAP: {
  1988.         struct v4l2_cropcap *cap = arg;
  1989.         pr_debug("   case VIDIOC_CROPCAP\n");
  1990.         if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
  1991.             cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
  1992.             retval = -EINVAL;
  1993.             break;
  1994.         }
  1995.         cap->bounds = cam->crop_bounds;
  1996.         cap->defrect = cam->crop_defrect;
  1997.         break;
  1998.     }
  1999.  
  2000.     /*!
  2001.      * V4l2 VIDIOC_G_CROP ioctl
  2002.      */
  2003.     case VIDIOC_G_CROP: {
  2004.         struct v4l2_crop *crop = arg;
  2005.         pr_debug("   case VIDIOC_G_CROP\n");
  2006.  
  2007.         if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
  2008.             crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
  2009.             retval = -EINVAL;
  2010.             break;
  2011.         }
  2012.         crop->c = cam->crop_current;
  2013.         break;
  2014.     }
  2015.  
  2016.     /*!
  2017.      * V4l2 VIDIOC_S_CROP ioctl
  2018.      */
  2019.     case VIDIOC_S_CROP: {
  2020.         struct v4l2_crop *crop = arg;
  2021.         struct v4l2_rect *b = &cam->crop_bounds;
  2022.         pr_debug("   case VIDIOC_S_CROP\n");
  2023.  
  2024.         if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
  2025.             crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
  2026.             retval = -EINVAL;
  2027.             break;
  2028.         }
  2029.  
  2030.         crop->c.top = (crop->c.top < b->top) ? b->top
  2031.                   : crop->c.top;
  2032.         if (crop->c.top > b->top + b->height)
  2033.             crop->c.top = b->top + b->height - 1;
  2034.         if (crop->c.height > b->top + b->height - crop->c.top)
  2035.             crop->c.height =
  2036.                 b->top + b->height - crop->c.top;
  2037.  
  2038.         crop->c.left = (crop->c.left < b->left) ? b->left
  2039.             : crop->c.left;
  2040.         if (crop->c.left > b->left + b->width)
  2041.             crop->c.left = b->left + b->width - 1;
  2042.         if (crop->c.width > b->left - crop->c.left + b->width)
  2043.             crop->c.width =
  2044.                 b->left - crop->c.left + b->width;
  2045.  
  2046.         crop->c.width -= crop->c.width % 8;
  2047.         crop->c.left -= crop->c.left % 4;
  2048.         cam->crop_current = crop->c;
  2049.  
  2050.         pr_debug("   Cropping Input to ipu size %d x %d\n",
  2051.                 cam->crop_current.width,
  2052.                 cam->crop_current.height);
  2053.         ipu_csi_set_window_size(cam->crop_current.width,
  2054.                     cam->crop_current.height,
  2055.                     cam->csi);
  2056.         ipu_csi_set_window_pos(cam->crop_current.left,
  2057.                        cam->crop_current.top,
  2058.                        cam->csi);
  2059.         break;
  2060.     }
  2061.  
  2062.     /*!
  2063.      * V4l2 VIDIOC_OVERLAY ioctl
  2064.      */
  2065.     case VIDIOC_OVERLAY: {
  2066.         int *on = arg;
  2067.         pr_debug("   VIDIOC_OVERLAY on=%d\n", *on);
  2068.         if (*on) {
  2069.             cam->overlay_on = true;
  2070.             cam->overlay_pid = current->pid;
  2071.             retval = start_preview(cam);
  2072.         }
  2073.         if (!*on) {
  2074.             retval = stop_preview(cam);
  2075.             cam->overlay_on = false;
  2076.         }
  2077.         break;
  2078.     }
  2079.  
  2080.     /*!
  2081.      * V4l2 VIDIOC_G_FBUF ioctl
  2082.      */
  2083.     case VIDIOC_G_FBUF: {
  2084.         struct v4l2_framebuffer *fb = arg;
  2085.         pr_debug("   case VIDIOC_G_FBUF\n");
  2086.         *fb = cam->v4l2_fb;
  2087.         fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
  2088.         break;
  2089.     }
  2090.  
  2091.     /*!
  2092.      * V4l2 VIDIOC_S_FBUF ioctl
  2093.      */
  2094.     case VIDIOC_S_FBUF: {
  2095.         struct v4l2_framebuffer *fb = arg;
  2096.         pr_debug("   case VIDIOC_S_FBUF\n");
  2097.         cam->v4l2_fb = *fb;
  2098.         break;
  2099.     }
  2100.  
  2101.     case VIDIOC_G_PARM: {
  2102.         struct v4l2_streamparm *parm = arg;
  2103.         pr_debug("   case VIDIOC_G_PARM\n");
  2104.         if (cam->sensor)
  2105.             retval = vidioc_int_g_parm(cam->sensor, parm);
  2106.         else {
  2107.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  2108.             retval = -ENODEV;
  2109.         }
  2110.         break;
  2111.     }
  2112.  
  2113.     case VIDIOC_S_PARM:  {
  2114.         struct v4l2_streamparm *parm = arg;
  2115.         pr_debug("   case VIDIOC_S_PARM\n");
  2116.         if (cam->sensor)
  2117.             retval = mxc_v4l2_s_param(cam, parm);
  2118.         else {
  2119.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  2120.             retval = -ENODEV;
  2121.         }
  2122.         break;
  2123.     }
  2124.  
  2125.     /* linux v4l2 bug, kernel c0485619 user c0405619 */
  2126.     case VIDIOC_ENUMSTD: {
  2127.         struct v4l2_standard *e = arg;
  2128.         pr_debug("   case VIDIOC_ENUMSTD\n");
  2129.         *e = cam->standard;
  2130.         break;
  2131.     }
  2132.  
  2133.     case VIDIOC_G_STD: {
  2134.         v4l2_std_id *e = arg;
  2135.         pr_debug("   case VIDIOC_G_STD\n");
  2136.         if (cam->sensor)
  2137.             retval = mxc_v4l2_g_std(cam, e);
  2138.         else {
  2139.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  2140.             retval = -ENODEV;
  2141.         }
  2142.         break;
  2143.     }
  2144.  
  2145.     case VIDIOC_S_STD: {
  2146.         v4l2_std_id *e = arg;
  2147.         pr_debug("   case VIDIOC_S_STD\n");
  2148.         retval = mxc_v4l2_s_std(cam, *e);
  2149.  
  2150.         break;
  2151.     }
  2152.  
  2153.     case VIDIOC_ENUMOUTPUT: {
  2154.         struct v4l2_output *output = arg;
  2155.         pr_debug("   case VIDIOC_ENUMOUTPUT\n");
  2156.         if (output->index >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) {
  2157.             retval = -EINVAL;
  2158.             break;
  2159.         }
  2160.         *output = mxc_capture_outputs[output->index];
  2161.  
  2162.         break;
  2163.     }
  2164.     case VIDIOC_G_OUTPUT: {
  2165.         int *p_output_num = arg;
  2166.         pr_debug("   case VIDIOC_G_OUTPUT\n");
  2167.         *p_output_num = cam->output;
  2168.         break;
  2169.     }
  2170.  
  2171.     case VIDIOC_S_OUTPUT: {
  2172.         int *p_output_num = arg;
  2173.         pr_debug("   case VIDIOC_S_OUTPUT\n");
  2174.         if (*p_output_num >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) {
  2175.             retval = -EINVAL;
  2176.             break;
  2177.         }
  2178.         cam->output = *p_output_num;
  2179.         break;
  2180.     }
  2181.  
  2182.     case VIDIOC_ENUMINPUT: {
  2183.         struct v4l2_input *input = arg;
  2184.         pr_debug("   case VIDIOC_ENUMINPUT\n");
  2185.         if (input->index >= MXC_V4L2_CAPTURE_NUM_INPUTS) {
  2186.             retval = -EINVAL;
  2187.             break;
  2188.         }
  2189.         *input = mxc_capture_inputs[input->index];
  2190.         break;
  2191.     }
  2192.  
  2193.     case VIDIOC_G_INPUT: {
  2194.         int *index = arg;
  2195.         pr_debug("   case VIDIOC_G_INPUT\n");
  2196.         *index = cam->current_input;
  2197.         if (cam->sensor) {
  2198.             int cam_input = 0;
  2199.             retval = vidioc_int_g_input(cam->sensor, &cam_input);
  2200.             /* Mix input of path (0x0000000X) with input of camera (0x000000X0) */
  2201.             if(!retval)
  2202.                 *index |= cam_input << 4;
  2203.         }
  2204.         else {
  2205.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  2206.             retval = -ENODEV;
  2207.         }
  2208.         break;
  2209.     }
  2210.  
  2211.     case VIDIOC_S_INPUT: {
  2212.         int *index = arg;
  2213.         pr_debug("   case VIDIOC_S_INPUT\n");
  2214.        
  2215.         if (cam->sensor) {
  2216.             int cam_input = *index >> 4;
  2217.             retval = vidioc_int_s_input(cam->sensor, &cam_input);
  2218.         }
  2219.         else {
  2220.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  2221.             retval = -ENODEV;
  2222.         }  
  2223.         *index &= 0x0F;
  2224.        
  2225.         if (*index >= MXC_V4L2_CAPTURE_NUM_INPUTS) {
  2226.             retval = -EINVAL;
  2227.             break;
  2228.         }
  2229.  
  2230.         if (*index == cam->current_input)
  2231.             break;
  2232.  
  2233.         if ((mxc_capture_inputs[cam->current_input].status &
  2234.             V4L2_IN_ST_NO_POWER) == 0) {
  2235.             retval = mxc_streamoff(cam);
  2236.             if (retval)
  2237.                 break;
  2238.             mxc_capture_inputs[cam->current_input].status |=
  2239.                             V4L2_IN_ST_NO_POWER;
  2240.         }
  2241.  
  2242.         if (strcmp(mxc_capture_inputs[*index].name, "CSI MEM") == 0) {
  2243. #if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)
  2244.             retval = csi_enc_select(cam);
  2245.             if (retval)
  2246.                 break;
  2247. #endif
  2248.         } else if (strcmp(mxc_capture_inputs[*index].name,
  2249.                   "CSI IC MEM") == 0) {
  2250. #if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
  2251.             retval = prp_enc_select(cam);
  2252.             if (retval)
  2253.                 break;
  2254. #endif
  2255.         }
  2256.  
  2257.         mxc_capture_inputs[*index].status &= ~V4L2_IN_ST_NO_POWER;
  2258.         cam->current_input = *index;
  2259.         break;
  2260.     }
  2261.     case VIDIOC_ENUM_FMT: {
  2262.         struct v4l2_fmtdesc *f = arg;
  2263.         if (cam->sensor)
  2264.             retval = vidioc_int_enum_fmt_cap(cam->sensor, f);
  2265.         else {
  2266.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  2267.             retval = -ENODEV;
  2268.         }
  2269.         break;
  2270.     }
  2271.     case VIDIOC_ENUM_FRAMESIZES: {
  2272.         struct v4l2_frmsizeenum *fsize = arg;
  2273.         if (cam->sensor)
  2274.             retval = vidioc_int_enum_framesizes(cam->sensor, fsize);
  2275.         else {
  2276.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  2277.             retval = -ENODEV;
  2278.         }
  2279.         break;
  2280.     }
  2281.     case VIDIOC_DBG_G_CHIP_IDENT: {
  2282.         struct v4l2_dbg_chip_ident *p = arg;
  2283.         p->ident = V4L2_IDENT_NONE;
  2284.         p->revision = 0;
  2285.         if (cam->sensor)
  2286.             retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p);
  2287.         else {
  2288.             pr_err("ERROR: v4l2 capture: slave not found!\n");
  2289.             retval = -ENODEV;
  2290.         }
  2291.         break;
  2292.     }
  2293.     case VIDIOC_TRY_FMT:
  2294.     case VIDIOC_QUERYCTRL:
  2295.     case VIDIOC_G_TUNER:
  2296.     case VIDIOC_S_TUNER:
  2297.     case VIDIOC_G_FREQUENCY:
  2298.     case VIDIOC_S_FREQUENCY:
  2299.     default:
  2300.         pr_debug("   case default or not supported\n");
  2301.         retval = -EINVAL;
  2302.         break;
  2303.     }
  2304.  
  2305.     up(&cam->busy_lock);
  2306.     return retval;
  2307. }
  2308.  
  2309. /*
  2310.  * V4L interface - ioctl function
  2311.  *
  2312.  * @return  None
  2313.  */
  2314. static long mxc_v4l_ioctl(struct file *file, unsigned int cmd,
  2315.              unsigned long arg)
  2316. {
  2317.     pr_debug("In MVC:mxc_v4l_ioctl\n");
  2318.     return video_usercopy(file, cmd, arg, mxc_v4l_do_ioctl);
  2319. }
  2320.  
  2321. /*!
  2322.  * V4L interface - mmap function
  2323.  *
  2324.  * @param file        structure file *
  2325.  *
  2326.  * @param vma         structure vm_area_struct *
  2327.  *
  2328.  * @return status     0 Success, EINTR busy lock error, ENOBUFS remap_page error
  2329.  */
  2330. static int mxc_mmap(struct file *file, struct vm_area_struct *vma)
  2331. {
  2332.     struct video_device *dev = video_devdata(file);
  2333.     unsigned long size;
  2334.     int res = 0;
  2335.     cam_data *cam = video_get_drvdata(dev);
  2336.  
  2337.     pr_debug("In MVC:mxc_mmap\n");
  2338.     pr_debug("   pgoff=0x%lx, start=0x%lx, end=0x%lx\n",
  2339.          vma->vm_pgoff, vma->vm_start, vma->vm_end);
  2340.  
  2341.     /* make this _really_ smp-safe */
  2342.     if (down_interruptible(&cam->busy_lock))
  2343.         return -EINTR;
  2344.  
  2345.     size = vma->vm_end - vma->vm_start;
  2346.     vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
  2347.  
  2348.     if (remap_pfn_range(vma, vma->vm_start,
  2349.                 vma->vm_pgoff, size, vma->vm_page_prot)) {
  2350.         pr_err("ERROR: v4l2 capture: mxc_mmap: "
  2351.             "remap_pfn_range failed\n");
  2352.         res = -ENOBUFS;
  2353.         goto mxc_mmap_exit;
  2354.     }
  2355.  
  2356.     vma->vm_flags &= ~VM_IO;    /* using shared anonymous pages */
  2357.  
  2358.       mxc_mmap_exit:
  2359.     up(&cam->busy_lock);
  2360.     return res;
  2361. }
  2362.  
  2363. /*!
  2364.  * V4L interface - poll function
  2365.  *
  2366.  * @param file       structure file *
  2367.  *
  2368.  * @param wait       structure poll_table_struct *
  2369.  *
  2370.  * @return  status   POLLIN | POLLRDNORM
  2371.  */
  2372. static unsigned int mxc_poll(struct file *file, struct poll_table_struct *wait)
  2373. {
  2374.     struct video_device *dev = video_devdata(file);
  2375.     cam_data *cam = video_get_drvdata(dev);
  2376.     wait_queue_head_t *queue = NULL;
  2377.     int res = POLLIN | POLLRDNORM;
  2378.  
  2379.     pr_debug("In MVC:mxc_poll\n");
  2380.  
  2381.     if (down_interruptible(&cam->busy_lock))
  2382.         return -EINTR;
  2383.  
  2384.     queue = &cam->enc_queue;
  2385.     poll_wait(file, queue, wait);
  2386.  
  2387.     up(&cam->busy_lock);
  2388.  
  2389.     return res;
  2390. }
  2391.  
  2392. /*!
  2393.  * This structure defines the functions to be called in this driver.
  2394.  */
  2395. static struct v4l2_file_operations mxc_v4l_fops = {
  2396.     .owner = THIS_MODULE,
  2397.     .open = mxc_v4l_open,
  2398.     .release = mxc_v4l_close,
  2399.     .read = mxc_v4l_read,
  2400.     .ioctl = mxc_v4l_ioctl,
  2401.     .mmap = mxc_mmap,
  2402.     .poll = mxc_poll,
  2403. };
  2404.  
  2405. static struct video_device mxc_v4l_template = {
  2406.     .name = "Mxc Camera",
  2407.     .fops = &mxc_v4l_fops,
  2408.     .release = video_device_release,
  2409. };
  2410.  
  2411. /*!
  2412.  * This function can be used to release any platform data on closing.
  2413.  */
  2414. static void camera_platform_release(struct device *device)
  2415. {
  2416. }
  2417.  
  2418. /*!
  2419.  * Camera V4l2 callback function.
  2420.  *
  2421.  * @param mask      u32
  2422.  *
  2423.  * @param dev       void device structure
  2424.  *
  2425.  * @return status
  2426.  */
  2427. static void camera_callback(u32 mask, void *dev)
  2428. {
  2429.     struct mxc_v4l_frame *done_frame;
  2430.     struct mxc_v4l_frame *ready_frame;
  2431.     struct timeval cur_time;
  2432.  
  2433.     cam_data *cam = (cam_data *) dev;
  2434.     if (cam == NULL)
  2435.         return;
  2436.  
  2437.     pr_debug("In MVC:camera_callback\n");
  2438.  
  2439.     if (!list_empty(&cam->working_q)) {
  2440.         do_gettimeofday(&cur_time);
  2441.  
  2442.         done_frame = list_entry(cam->working_q.next,
  2443.                     struct mxc_v4l_frame,
  2444.                     queue);
  2445.  
  2446.         if (done_frame->ipu_buf_num != local_buf_num)
  2447.             goto next;
  2448.  
  2449.         /*
  2450.          * Set the current time to done frame buffer's
  2451.          * timestamp. Users can use this information to judge
  2452.          * the frame's usage.
  2453.          */
  2454.         done_frame->buffer.timestamp = cur_time;
  2455.  
  2456.         if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {
  2457.             done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE;
  2458.             done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;
  2459.  
  2460.             /* Added to the done queue */
  2461.             list_del(cam->working_q.next);
  2462.             list_add_tail(&done_frame->queue, &cam->done_q);
  2463.  
  2464.             /* Wake up the queue */
  2465.             cam->enc_counter++;
  2466.             wake_up_interruptible(&cam->enc_queue);
  2467.         } else
  2468.             pr_err("ERROR: v4l2 capture: camera_callback: "
  2469.                 "buffer not queued\n");
  2470.     }
  2471.  
  2472. next:
  2473.     if (!list_empty(&cam->ready_q)) {
  2474.         ready_frame = list_entry(cam->ready_q.next,
  2475.                      struct mxc_v4l_frame,
  2476.                      queue);
  2477.         if (cam->enc_update_eba)
  2478.             if (cam->enc_update_eba(ready_frame->buffer.m.offset,
  2479.                         &cam->ping_pong_csi) == 0) {
  2480.                 list_del(cam->ready_q.next);
  2481.                 list_add_tail(&ready_frame->queue,
  2482.                           &cam->working_q);
  2483.                 ready_frame->ipu_buf_num = local_buf_num;
  2484.             }
  2485.     } else {
  2486.         if (cam->enc_update_eba)
  2487.             cam->enc_update_eba(
  2488.                 cam->dummy_frame.buffer.m.offset,
  2489.                 &cam->ping_pong_csi);
  2490.     }
  2491.  
  2492.     local_buf_num = (local_buf_num == 0) ? 1 : 0;
  2493.  
  2494.     return;
  2495. }
  2496.  
  2497. /*!
  2498.  * initialize cam_data structure
  2499.  *
  2500.  * @param cam      structure cam_data *
  2501.  *
  2502.  * @return status  0 Success
  2503.  */
  2504. static void init_camera_struct(cam_data *cam, struct platform_device *pdev)
  2505. {
  2506.     pr_debug("In MVC: init_camera_struct\n");
  2507.  
  2508.     /* Default everything to 0 */
  2509.     memset(cam, 0, sizeof(cam_data));
  2510.  
  2511.     init_MUTEX(&cam->param_lock);
  2512.     init_MUTEX(&cam->busy_lock);
  2513.  
  2514.     cam->video_dev = video_device_alloc();
  2515.     if (cam->video_dev == NULL)
  2516.         return;
  2517.  
  2518.     *(cam->video_dev) = mxc_v4l_template;
  2519.  
  2520.     video_set_drvdata(cam->video_dev, cam);
  2521.     dev_set_drvdata(&pdev->dev, (void *)cam);
  2522.     cam->video_dev->minor = -1;
  2523.  
  2524.     init_waitqueue_head(&cam->enc_queue);
  2525.     init_waitqueue_head(&cam->still_queue);
  2526.  
  2527.     /* setup cropping */
  2528.     cam->crop_bounds.left = 0;
  2529.     cam->crop_bounds.width = 640;
  2530.     cam->crop_bounds.top = 0;
  2531.     cam->crop_bounds.height = 480;
  2532.     cam->crop_current = cam->crop_defrect = cam->crop_bounds;
  2533.     ipu_csi_set_window_size(cam->crop_current.width,
  2534.                 cam->crop_current.height, cam->csi);
  2535.     ipu_csi_set_window_pos(cam->crop_current.left,
  2536.                 cam->crop_current.top, cam->csi);
  2537.     cam->streamparm.parm.capture.capturemode = 0;
  2538.  
  2539.     cam->standard.index = 0;
  2540.     cam->standard.id = V4L2_STD_UNKNOWN;
  2541.     cam->standard.frameperiod.denominator = 30;
  2542.     cam->standard.frameperiod.numerator = 1;
  2543.     cam->standard.framelines = 480;
  2544.     cam->standard_autodetect = true;
  2545.     cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  2546.     cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod;
  2547.     cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
  2548.     cam->overlay_on = false;
  2549.     cam->capture_on = false;
  2550.     cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY;
  2551.  
  2552.     cam->v2f.fmt.pix.sizeimage = 352 * 288 * 3 / 2;
  2553.     cam->v2f.fmt.pix.bytesperline = 288 * 3 / 2;
  2554.     cam->v2f.fmt.pix.width = 288;
  2555.     cam->v2f.fmt.pix.height = 352;
  2556.     cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
  2557.     cam->win.w.width = 160;
  2558.     cam->win.w.height = 160;
  2559.     cam->win.w.left = 0;
  2560.     cam->win.w.top = 0;
  2561.  
  2562.     cam->csi = 0;  /* Need to determine how to set this correctly with
  2563.             * multiple video input devices. */
  2564.  
  2565.     cam->enc_callback = camera_callback;
  2566.     init_waitqueue_head(&cam->power_queue);
  2567.     spin_lock_init(&cam->queue_int_lock);
  2568.     spin_lock_init(&cam->dqueue_int_lock);
  2569. }
  2570.  
  2571. static ssize_t show_streaming(struct device *dev,
  2572.             struct device_attribute *attr, char *buf)
  2573. {
  2574.     struct video_device *video_dev = container_of(dev,
  2575.                         struct video_device, dev);
  2576.     cam_data *g_cam = video_get_drvdata(video_dev);
  2577.  
  2578.     if (g_cam->capture_on)
  2579.         return sprintf(buf, "stream on\n");
  2580.     else
  2581.         return sprintf(buf, "stream off\n");
  2582. }
  2583. static DEVICE_ATTR(fsl_v4l2_capture_property, S_IRUGO, show_streaming, NULL);
  2584.  
  2585. static ssize_t show_overlay(struct device *dev,
  2586.             struct device_attribute *attr, char *buf)
  2587. {
  2588.     struct video_device *video_dev = container_of(dev,
  2589.                         struct video_device, dev);
  2590.     cam_data *g_cam = video_get_drvdata(video_dev);
  2591.  
  2592.     if (g_cam->overlay_on)
  2593.         return sprintf(buf, "overlay on\n");
  2594.     else
  2595.         return sprintf(buf, "overlay off\n");
  2596. }
  2597. static DEVICE_ATTR(fsl_v4l2_overlay_property, S_IRUGO, show_overlay, NULL);
  2598.  
  2599. /*!
  2600.  * This function is called to probe the devices if registered.
  2601.  *
  2602.  * @param   pdev  the device structure used to give information on which device
  2603.  *                to probe
  2604.  *
  2605.  * @return  The function returns 0 on success and -1 on failure.
  2606.  */
  2607. static int mxc_v4l2_probe(struct platform_device *pdev)
  2608. {
  2609.     /* Create g_cam and initialize it. */
  2610.     g_cam = kmalloc(sizeof(cam_data), GFP_KERNEL);
  2611.     if (g_cam == NULL) {
  2612.         pr_err("ERROR: v4l2 capture: failed to register camera\n");
  2613.         return -1;
  2614.     }
  2615.     init_camera_struct(g_cam, pdev);
  2616.     pdev->dev.release = camera_platform_release;
  2617.  
  2618.     /* Set up the v4l2 device and register it*/
  2619.     mxc_v4l2_int_device.priv = g_cam;
  2620.     /* This function contains a bug that won't let this be rmmod'd. */
  2621.     v4l2_int_device_register(&mxc_v4l2_int_device);
  2622.  
  2623.     /* register v4l video device */
  2624.     if (video_register_device(g_cam->video_dev, VFL_TYPE_GRABBER, video_nr)
  2625.         == -1) {
  2626.         kfree(g_cam);
  2627.         g_cam = NULL;
  2628.         pr_err("ERROR: v4l2 capture: video_register_device failed\n");
  2629.         return -1;
  2630.     }
  2631.     pr_debug("   Video device registered: %s #%d\n",
  2632.          g_cam->video_dev->name, g_cam->video_dev->minor);
  2633.  
  2634.     if (device_create_file(&g_cam->video_dev->dev,
  2635.             &dev_attr_fsl_v4l2_capture_property))
  2636.         dev_err(&pdev->dev, "Error on creating sysfs file"
  2637.             " for capture\n");
  2638.  
  2639.     if (device_create_file(&g_cam->video_dev->dev,
  2640.             &dev_attr_fsl_v4l2_overlay_property))
  2641.         dev_err(&pdev->dev, "Error on creating sysfs file"
  2642.             " for overlay\n");
  2643.  
  2644.     return 0;
  2645. }
  2646.  
  2647. /*!
  2648.  * This function is called to remove the devices when device unregistered.
  2649.  *
  2650.  * @param   pdev  the device structure used to give information on which device
  2651.  *                to remove
  2652.  *
  2653.  * @return  The function returns 0 on success and -1 on failure.
  2654.  */
  2655. static int mxc_v4l2_remove(struct platform_device *pdev)
  2656. {
  2657.  
  2658.     if (g_cam->open_count) {
  2659.         pr_err("ERROR: v4l2 capture:camera open "
  2660.             "-- setting ops to NULL\n");
  2661.         return -EBUSY;
  2662.     } else {
  2663.         device_remove_file(&g_cam->video_dev->dev,
  2664.             &dev_attr_fsl_v4l2_capture_property);
  2665.         device_remove_file(&g_cam->video_dev->dev,
  2666.             &dev_attr_fsl_v4l2_overlay_property);
  2667.  
  2668.         pr_info("V4L2 freeing image input device\n");
  2669.         v4l2_int_device_unregister(&mxc_v4l2_int_device);
  2670.         video_unregister_device(g_cam->video_dev);
  2671.  
  2672.         mxc_free_frame_buf(g_cam);
  2673.         kfree(g_cam);
  2674.         g_cam = NULL;
  2675.     }
  2676.  
  2677.     pr_info("V4L2 unregistering video\n");
  2678.     return 0;
  2679. }
  2680.  
  2681. /*!
  2682.  * This function is called to put the sensor in a low power state.
  2683.  * Refer to the document driver-model/driver.txt in the kernel source tree
  2684.  * for more information.
  2685.  *
  2686.  * @param   pdev  the device structure used to give information on which I2C
  2687.  *                to suspend
  2688.  * @param   state the power state the device is entering
  2689.  *
  2690.  * @return  The function returns 0 on success and -1 on failure.
  2691.  */
  2692. static int mxc_v4l2_suspend(struct platform_device *pdev, pm_message_t state)
  2693. {
  2694.     cam_data *cam = platform_get_drvdata(pdev);
  2695.  
  2696.     pr_debug("In MVC:mxc_v4l2_suspend\n");
  2697.  
  2698.     if (cam == NULL) {
  2699.         return -1;
  2700.     }
  2701.  
  2702.     cam->low_power = true;
  2703.  
  2704.     if (cam->overlay_on == true)
  2705.         stop_preview(cam);
  2706.     if ((cam->capture_on == true) && cam->enc_disable) {
  2707.         cam->enc_disable(cam);
  2708.     }
  2709.  
  2710.     if (cam->sensor)
  2711.         vidioc_int_s_power(cam->sensor, 0);
  2712.  
  2713.     return 0;
  2714. }
  2715.  
  2716. /*!
  2717.  * This function is called to bring the sensor back from a low power state.
  2718.  * Refer to the document driver-model/driver.txt in the kernel source tree
  2719.  * for more information.
  2720.  *
  2721.  * @param   pdev   the device structure
  2722.  *
  2723.  * @return  The function returns 0 on success and -1 on failure
  2724.  */
  2725. static int mxc_v4l2_resume(struct platform_device *pdev)
  2726. {
  2727.     cam_data *cam = platform_get_drvdata(pdev);
  2728.  
  2729.     pr_debug("In MVC:mxc_v4l2_resume\n");
  2730.  
  2731.     if (cam == NULL) {
  2732.         return -1;
  2733.     }
  2734.  
  2735.     cam->low_power = false;
  2736.     wake_up_interruptible(&cam->power_queue);
  2737.  
  2738.     if (cam->sensor)
  2739.         vidioc_int_s_power(cam->sensor, 1);
  2740.  
  2741.     if (cam->overlay_on == true)
  2742.         start_preview(cam);
  2743.     if (cam->capture_on == true)
  2744.         mxc_streamon(cam);
  2745.  
  2746.     return 0;
  2747. }
  2748.  
  2749. /*!
  2750.  * This structure contains pointers to the power management callback functions.
  2751.  */
  2752. static struct platform_driver mxc_v4l2_driver = {
  2753.     .driver = {
  2754.            .name = "mxc_v4l2_capture",
  2755.            },
  2756.     .probe = mxc_v4l2_probe,
  2757.     .remove = mxc_v4l2_remove,
  2758.     .suspend = mxc_v4l2_suspend,
  2759.     .resume = mxc_v4l2_resume,
  2760.     .shutdown = NULL,
  2761. };
  2762.  
  2763. /*!
  2764.  * Initializes the camera driver.
  2765.  */
  2766. static int mxc_v4l2_master_attach(struct v4l2_int_device *slave)
  2767. {
  2768.     cam_data *cam = slave->u.slave->master->priv;
  2769.     struct v4l2_format cam_fmt;
  2770.  
  2771.     pr_debug("In MVC: mxc_v4l2_master_attach\n");
  2772.     pr_debug("   slave.name = %s\n", slave->name);
  2773.     pr_debug("   master.name = %s\n", slave->u.slave->master->name);
  2774.  
  2775.     cam->sensor = slave;
  2776.     if (slave == NULL) {
  2777.         pr_err("ERROR: v4l2 capture: slave parameter not valid.\n");
  2778.         return -1;
  2779.     }
  2780.  
  2781.     ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, true, true);
  2782.     vidioc_int_s_power(cam->sensor, 1);
  2783.     vidioc_int_dev_init(slave);
  2784.     ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, false, false);
  2785.     cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  2786.     vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
  2787.  
  2788.     /* Used to detect TV in (type 1) vs. camera (type 0)*/
  2789.     cam->device_type = cam_fmt.fmt.pix.priv;
  2790.  
  2791.     /* Set the input size to the ipu for this device */
  2792.     cam->crop_bounds.top = cam->crop_bounds.left = 0;
  2793.     cam->crop_bounds.width = cam_fmt.fmt.pix.width;
  2794.     cam->crop_bounds.height = cam_fmt.fmt.pix.height;
  2795.  
  2796.     /* This also is the max crop size for this device. */
  2797.     cam->crop_defrect.top = cam->crop_defrect.left = 0;
  2798.     cam->crop_defrect.width = cam_fmt.fmt.pix.width;
  2799.     cam->crop_defrect.height = cam_fmt.fmt.pix.height;
  2800.  
  2801.     /* At this point, this is also the current image size. */
  2802.     cam->crop_current.top = cam->crop_current.left = 0;
  2803.     cam->crop_current.width = cam_fmt.fmt.pix.width;
  2804.     cam->crop_current.height = cam_fmt.fmt.pix.height;
  2805.  
  2806.     pr_debug("End of %s: v2f pix widthxheight %d x %d\n",
  2807.          __func__,
  2808.          cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height);
  2809.     pr_debug("End of %s: crop_bounds widthxheight %d x %d\n",
  2810.          __func__,
  2811.          cam->crop_bounds.width, cam->crop_bounds.height);
  2812.     pr_debug("End of %s: crop_defrect widthxheight %d x %d\n",
  2813.          __func__,
  2814.          cam->crop_defrect.width, cam->crop_defrect.height);
  2815.     pr_debug("End of %s: crop_current widthxheight %d x %d\n",
  2816.          __func__,
  2817.          cam->crop_current.width, cam->crop_current.height);
  2818.  
  2819.     return 0;
  2820. }
  2821.  
  2822. /*!
  2823.  * Disconnects the camera driver.
  2824.  */
  2825. static void mxc_v4l2_master_detach(struct v4l2_int_device *slave)
  2826. {
  2827.     pr_debug("In MVC:mxc_v4l2_master_detach\n");
  2828.     vidioc_int_dev_exit(slave);
  2829. }
  2830.  
  2831. /*!
  2832.  * Entry point for the V4L2
  2833.  *
  2834.  * @return  Error code indicating success or failure
  2835.  */
  2836. static __init int camera_init(void)
  2837. {
  2838.     u8 err = 0;
  2839.  
  2840.     pr_debug("In MVC:camera_init\n");
  2841.  
  2842.     /* Register the device driver structure. */
  2843.     err = platform_driver_register(&mxc_v4l2_driver);
  2844.     if (err != 0) {
  2845.         pr_err("ERROR: v4l2 capture:camera_init: "
  2846.             "platform_driver_register failed.\n");
  2847.         return err;
  2848.     }
  2849.  
  2850.     return err;
  2851. }
  2852.  
  2853. /*!
  2854.  * Exit and cleanup for the V4L2
  2855.  */
  2856. static void __exit camera_exit(void)
  2857. {
  2858.     pr_debug("In MVC: camera_exit\n");
  2859.  
  2860.     platform_driver_unregister(&mxc_v4l2_driver);
  2861. }
  2862.  
  2863. module_init(camera_init);
  2864. module_exit(camera_exit);
  2865.  
  2866. module_param(video_nr, int, 0444);
  2867. MODULE_AUTHOR("Freescale Semiconductor, Inc.");
  2868. MODULE_DESCRIPTION("V4L2 capture driver for Mxc based cameras");
  2869. MODULE_LICENSE("GPL");
  2870. MODULE_SUPPORTED_DEVICE("video");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement