diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/media/video/s5p-fimc')
-rw-r--r-- | ANDROID_3.4.5/drivers/media/video/s5p-fimc/Makefile | 5 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-capture.c | 1583 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-core.c | 2045 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-core.h | 826 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-mdevice.c | 862 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-mdevice.h | 118 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-reg.c | 723 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/media/video/s5p-fimc/mipi-csis.c | 729 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/media/video/s5p-fimc/mipi-csis.h | 25 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/media/video/s5p-fimc/regs-fimc.h | 301 |
10 files changed, 0 insertions, 7217 deletions
diff --git a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/Makefile b/ANDROID_3.4.5/drivers/media/video/s5p-fimc/Makefile deleted file mode 100644 index 33dec7f8..00000000 --- a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-capture.o fimc-mdevice.o -s5p-csis-objs := mipi-csis.o - -obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc.o diff --git a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-capture.c b/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-capture.c deleted file mode 100644 index 7e9b2c61..00000000 --- a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-capture.c +++ /dev/null @@ -1,1583 +0,0 @@ -/* - * Samsung S5P/EXYNOS4 SoC series camera interface (camera capture) driver - * - * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd. - * Author: Sylwester Nawrocki, <s.nawrocki@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/bug.h> -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/pm_runtime.h> -#include <linux/list.h> -#include <linux/slab.h> - -#include <linux/videodev2.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-mem2mem.h> -#include <media/videobuf2-core.h> -#include <media/videobuf2-dma-contig.h> - -#include "fimc-mdevice.h" -#include "fimc-core.h" - -static int fimc_init_capture(struct fimc_dev *fimc) -{ - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct fimc_sensor_info *sensor; - unsigned long flags; - int ret = 0; - - if (fimc->pipeline.sensor == NULL || ctx == NULL) - return -ENXIO; - if (ctx->s_frame.fmt == NULL) - return -EINVAL; - - sensor = v4l2_get_subdev_hostdata(fimc->pipeline.sensor); - - spin_lock_irqsave(&fimc->slock, flags); - fimc_prepare_dma_offset(ctx, &ctx->d_frame); - fimc_set_yuv_order(ctx); - - fimc_hw_set_camera_polarity(fimc, sensor->pdata); - fimc_hw_set_camera_type(fimc, sensor->pdata); - fimc_hw_set_camera_source(fimc, sensor->pdata); - fimc_hw_set_camera_offset(fimc, &ctx->s_frame); - - ret = fimc_set_scaler_info(ctx); - if (!ret) { - fimc_hw_set_input_path(ctx); - fimc_hw_set_prescaler(ctx); - fimc_hw_set_mainscaler(ctx); - fimc_hw_set_target_format(ctx); - fimc_hw_set_rotation(ctx); - fimc_hw_set_effect(ctx, false); - fimc_hw_set_output_path(ctx); - fimc_hw_set_out_dma(ctx); - if (fimc->variant->has_alpha) - fimc_hw_set_rgb_alpha(ctx); - clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); - } - spin_unlock_irqrestore(&fimc->slock, flags); - return ret; -} - -static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) -{ - struct fimc_vid_cap *cap = &fimc->vid_cap; - struct fimc_vid_buffer *buf; - unsigned long flags; - bool streaming; - - spin_lock_irqsave(&fimc->slock, flags); - streaming = fimc->state & (1 << ST_CAPT_ISP_STREAM); - - fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_SHUT | - 1 << ST_CAPT_STREAM | 1 << ST_CAPT_ISP_STREAM); - if (!suspend) - fimc->state &= ~(1 << ST_CAPT_PEND | 1 << ST_CAPT_SUSPENDED); - - /* Release unused buffers */ - while (!suspend && !list_empty(&cap->pending_buf_q)) { - buf = fimc_pending_queue_pop(cap); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - } - /* If suspending put unused buffers onto pending queue */ - while (!list_empty(&cap->active_buf_q)) { - buf = fimc_active_queue_pop(cap); - if (suspend) - fimc_pending_queue_add(cap, buf); - else - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - } - set_bit(ST_CAPT_SUSPENDED, &fimc->state); - - fimc_hw_reset(fimc); - cap->buf_index = 0; - - spin_unlock_irqrestore(&fimc->slock, flags); - - if (streaming) - return fimc_pipeline_s_stream(fimc, 0); - else - return 0; -} - -static int fimc_stop_capture(struct fimc_dev *fimc, bool suspend) -{ - unsigned long flags; - - if (!fimc_capture_active(fimc)) - return 0; - - spin_lock_irqsave(&fimc->slock, flags); - set_bit(ST_CAPT_SHUT, &fimc->state); - fimc_deactivate_capture(fimc); - spin_unlock_irqrestore(&fimc->slock, flags); - - wait_event_timeout(fimc->irq_queue, - !test_bit(ST_CAPT_SHUT, &fimc->state), - (2*HZ/10)); /* 200 ms */ - - return fimc_capture_state_cleanup(fimc, suspend); -} - -/** - * fimc_capture_config_update - apply the camera interface configuration - * - * To be called from within the interrupt handler with fimc.slock - * spinlock held. It updates the camera pixel crop, rotation and - * image flip in H/W. - */ -int fimc_capture_config_update(struct fimc_ctx *ctx) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - int ret; - - if (!test_bit(ST_CAPT_APPLY_CFG, &fimc->state)) - return 0; - - spin_lock(&ctx->slock); - fimc_hw_set_camera_offset(fimc, &ctx->s_frame); - ret = fimc_set_scaler_info(ctx); - if (ret == 0) { - fimc_hw_set_prescaler(ctx); - fimc_hw_set_mainscaler(ctx); - fimc_hw_set_target_format(ctx); - fimc_hw_set_rotation(ctx); - fimc_prepare_dma_offset(ctx, &ctx->d_frame); - fimc_hw_set_out_dma(ctx); - if (fimc->variant->has_alpha) - fimc_hw_set_rgb_alpha(ctx); - clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); - } - spin_unlock(&ctx->slock); - return ret; -} - -static int start_streaming(struct vb2_queue *q, unsigned int count) -{ - struct fimc_ctx *ctx = q->drv_priv; - struct fimc_dev *fimc = ctx->fimc_dev; - struct fimc_vid_cap *vid_cap = &fimc->vid_cap; - int min_bufs; - int ret; - - vid_cap->frame_count = 0; - - ret = fimc_init_capture(fimc); - if (ret) - goto error; - - set_bit(ST_CAPT_PEND, &fimc->state); - - min_bufs = fimc->vid_cap.reqbufs_count > 1 ? 2 : 1; - - if (vid_cap->active_buf_cnt >= min_bufs && - !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) { - fimc_activate_capture(ctx); - - if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) - fimc_pipeline_s_stream(fimc, 1); - } - - return 0; -error: - fimc_capture_state_cleanup(fimc, false); - return ret; -} - -static int stop_streaming(struct vb2_queue *q) -{ - struct fimc_ctx *ctx = q->drv_priv; - struct fimc_dev *fimc = ctx->fimc_dev; - - if (!fimc_capture_active(fimc)) - return -EINVAL; - - return fimc_stop_capture(fimc, false); -} - -int fimc_capture_suspend(struct fimc_dev *fimc) -{ - bool suspend = fimc_capture_busy(fimc); - - int ret = fimc_stop_capture(fimc, suspend); - if (ret) - return ret; - return fimc_pipeline_shutdown(fimc); -} - -static void buffer_queue(struct vb2_buffer *vb); - -int fimc_capture_resume(struct fimc_dev *fimc) -{ - struct fimc_vid_cap *vid_cap = &fimc->vid_cap; - struct fimc_vid_buffer *buf; - int i; - - if (!test_and_clear_bit(ST_CAPT_SUSPENDED, &fimc->state)) - return 0; - - INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); - vid_cap->buf_index = 0; - fimc_pipeline_initialize(fimc, &fimc->vid_cap.vfd->entity, - false); - fimc_init_capture(fimc); - - clear_bit(ST_CAPT_SUSPENDED, &fimc->state); - - for (i = 0; i < vid_cap->reqbufs_count; i++) { - if (list_empty(&vid_cap->pending_buf_q)) - break; - buf = fimc_pending_queue_pop(vid_cap); - buffer_queue(&buf->vb); - } - return 0; - -} - -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt, - unsigned int *num_buffers, unsigned int *num_planes, - unsigned int sizes[], void *allocators[]) -{ - const struct v4l2_pix_format_mplane *pixm = NULL; - struct fimc_ctx *ctx = vq->drv_priv; - struct fimc_frame *frame = &ctx->d_frame; - struct fimc_fmt *fmt = frame->fmt; - unsigned long wh; - int i; - - if (pfmt) { - pixm = &pfmt->fmt.pix_mp; - fmt = fimc_find_format(&pixm->pixelformat, NULL, - FMT_FLAGS_CAM | FMT_FLAGS_M2M, -1); - wh = pixm->width * pixm->height; - } else { - wh = frame->f_width * frame->f_height; - } - - if (fmt == NULL) - return -EINVAL; - - *num_planes = fmt->memplanes; - - for (i = 0; i < fmt->memplanes; i++) { - unsigned int size = (wh * fmt->depth[i]) / 8; - if (pixm) - sizes[i] = max(size, pixm->plane_fmt[i].sizeimage); - else - sizes[i] = size; - allocators[i] = ctx->fimc_dev->alloc_ctx; - } - - return 0; -} - -static int buffer_prepare(struct vb2_buffer *vb) -{ - struct vb2_queue *vq = vb->vb2_queue; - struct fimc_ctx *ctx = vq->drv_priv; - int i; - - if (ctx->d_frame.fmt == NULL) - return -EINVAL; - - for (i = 0; i < ctx->d_frame.fmt->memplanes; i++) { - unsigned long size = ctx->d_frame.payload[i]; - - if (vb2_plane_size(vb, i) < size) { - v4l2_err(ctx->fimc_dev->vid_cap.vfd, - "User buffer too small (%ld < %ld)\n", - vb2_plane_size(vb, i), size); - return -EINVAL; - } - vb2_set_plane_payload(vb, i, size); - } - - return 0; -} - -static void buffer_queue(struct vb2_buffer *vb) -{ - struct fimc_vid_buffer *buf - = container_of(vb, struct fimc_vid_buffer, vb); - struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - struct fimc_dev *fimc = ctx->fimc_dev; - struct fimc_vid_cap *vid_cap = &fimc->vid_cap; - unsigned long flags; - int min_bufs; - - spin_lock_irqsave(&fimc->slock, flags); - fimc_prepare_addr(ctx, &buf->vb, &ctx->d_frame, &buf->paddr); - - if (!test_bit(ST_CAPT_SUSPENDED, &fimc->state) && - !test_bit(ST_CAPT_STREAM, &fimc->state) && - vid_cap->active_buf_cnt < FIMC_MAX_OUT_BUFS) { - /* Setup the buffer directly for processing. */ - int buf_id = (vid_cap->reqbufs_count == 1) ? -1 : - vid_cap->buf_index; - - fimc_hw_set_output_addr(fimc, &buf->paddr, buf_id); - buf->index = vid_cap->buf_index; - fimc_active_queue_add(vid_cap, buf); - - if (++vid_cap->buf_index >= FIMC_MAX_OUT_BUFS) - vid_cap->buf_index = 0; - } else { - fimc_pending_queue_add(vid_cap, buf); - } - - min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1; - - - if (vb2_is_streaming(&vid_cap->vbq) && - vid_cap->active_buf_cnt >= min_bufs && - !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) { - fimc_activate_capture(ctx); - spin_unlock_irqrestore(&fimc->slock, flags); - - if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) - fimc_pipeline_s_stream(fimc, 1); - return; - } - spin_unlock_irqrestore(&fimc->slock, flags); -} - -static void fimc_lock(struct vb2_queue *vq) -{ - struct fimc_ctx *ctx = vb2_get_drv_priv(vq); - mutex_lock(&ctx->fimc_dev->lock); -} - -static void fimc_unlock(struct vb2_queue *vq) -{ - struct fimc_ctx *ctx = vb2_get_drv_priv(vq); - mutex_unlock(&ctx->fimc_dev->lock); -} - -static struct vb2_ops fimc_capture_qops = { - .queue_setup = queue_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .wait_prepare = fimc_unlock, - .wait_finish = fimc_lock, - .start_streaming = start_streaming, - .stop_streaming = stop_streaming, -}; - -/** - * fimc_capture_ctrls_create - initialize the control handler - * Initialize the capture video node control handler and fill it - * with the FIMC controls. Inherit any sensor's controls if the - * 'user_subdev_api' flag is false (default behaviour). - * This function need to be called with the graph mutex held. - */ -int fimc_capture_ctrls_create(struct fimc_dev *fimc) -{ - struct fimc_vid_cap *vid_cap = &fimc->vid_cap; - int ret; - - if (WARN_ON(vid_cap->ctx == NULL)) - return -ENXIO; - if (vid_cap->ctx->ctrls_rdy) - return 0; - - ret = fimc_ctrls_create(vid_cap->ctx); - if (ret || vid_cap->user_subdev_api) - return ret; - - return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrl_handler, - fimc->pipeline.sensor->ctrl_handler); -} - -static int fimc_capture_set_default_format(struct fimc_dev *fimc); - -static int fimc_capture_open(struct file *file) -{ - struct fimc_dev *fimc = video_drvdata(file); - int ret = v4l2_fh_open(file); - - if (ret) - return ret; - - dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); - - /* Return if the corresponding video mem2mem node is already opened. */ - if (fimc_m2m_active(fimc)) - return -EBUSY; - - set_bit(ST_CAPT_BUSY, &fimc->state); - pm_runtime_get_sync(&fimc->pdev->dev); - - if (++fimc->vid_cap.refcnt == 1) { - ret = fimc_pipeline_initialize(fimc, - &fimc->vid_cap.vfd->entity, true); - if (ret < 0) { - dev_err(&fimc->pdev->dev, - "Video pipeline initialization failed\n"); - pm_runtime_put_sync(&fimc->pdev->dev); - fimc->vid_cap.refcnt--; - v4l2_fh_release(file); - clear_bit(ST_CAPT_BUSY, &fimc->state); - return ret; - } - ret = fimc_capture_ctrls_create(fimc); - - if (!ret && !fimc->vid_cap.user_subdev_api) - ret = fimc_capture_set_default_format(fimc); - } - return ret; -} - -static int fimc_capture_close(struct file *file) -{ - struct fimc_dev *fimc = video_drvdata(file); - - dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); - - if (--fimc->vid_cap.refcnt == 0) { - clear_bit(ST_CAPT_BUSY, &fimc->state); - fimc_stop_capture(fimc, false); - fimc_pipeline_shutdown(fimc); - clear_bit(ST_CAPT_SUSPENDED, &fimc->state); - } - - pm_runtime_put(&fimc->pdev->dev); - - if (fimc->vid_cap.refcnt == 0) { - vb2_queue_release(&fimc->vid_cap.vbq); - fimc_ctrls_delete(fimc->vid_cap.ctx); - } - return v4l2_fh_release(file); -} - -static unsigned int fimc_capture_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct fimc_dev *fimc = video_drvdata(file); - - return vb2_poll(&fimc->vid_cap.vbq, file, wait); -} - -static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct fimc_dev *fimc = video_drvdata(file); - - return vb2_mmap(&fimc->vid_cap.vbq, vma); -} - -static const struct v4l2_file_operations fimc_capture_fops = { - .owner = THIS_MODULE, - .open = fimc_capture_open, - .release = fimc_capture_close, - .poll = fimc_capture_poll, - .unlocked_ioctl = video_ioctl2, - .mmap = fimc_capture_mmap, -}; - -/* - * Format and crop negotiation helpers - */ - -static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx, - u32 *width, u32 *height, - u32 *code, u32 *fourcc, int pad) -{ - bool rotation = ctx->rotation == 90 || ctx->rotation == 270; - struct fimc_dev *fimc = ctx->fimc_dev; - struct samsung_fimc_variant *var = fimc->variant; - struct fimc_pix_limit *pl = var->pix_limit; - struct fimc_frame *dst = &ctx->d_frame; - u32 depth, min_w, max_w, min_h, align_h = 3; - u32 mask = FMT_FLAGS_CAM; - struct fimc_fmt *ffmt; - - /* Color conversion from/to JPEG is not supported */ - if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE && - fimc_fmt_is_jpeg(ctx->s_frame.fmt->color)) - *code = V4L2_MBUS_FMT_JPEG_1X8; - - if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK) - mask |= FMT_FLAGS_M2M; - - ffmt = fimc_find_format(fourcc, code, mask, 0); - if (WARN_ON(!ffmt)) - return NULL; - if (code) - *code = ffmt->mbus_code; - if (fourcc) - *fourcc = ffmt->fourcc; - - if (pad == FIMC_SD_PAD_SINK) { - max_w = fimc_fmt_is_jpeg(ffmt->color) ? - pl->scaler_dis_w : pl->scaler_en_w; - /* Apply the camera input interface pixel constraints */ - v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4, - height, max_t(u32, *height, 32), - FIMC_CAMIF_MAX_HEIGHT, - fimc_fmt_is_jpeg(ffmt->color) ? 3 : 1, - 0); - return ffmt; - } - /* Can't scale or crop in transparent (JPEG) transfer mode */ - if (fimc_fmt_is_jpeg(ffmt->color)) { - *width = ctx->s_frame.f_width; - *height = ctx->s_frame.f_height; - return ffmt; - } - /* Apply the scaler and the output DMA constraints */ - max_w = rotation ? pl->out_rot_en_w : pl->out_rot_dis_w; - min_w = ctx->state & FIMC_DST_CROP ? dst->width : var->min_out_pixsize; - min_h = ctx->state & FIMC_DST_CROP ? dst->height : var->min_out_pixsize; - if (var->min_vsize_align == 1 && !rotation) - align_h = fimc_fmt_is_rgb(ffmt->color) ? 0 : 1; - - depth = fimc_get_format_depth(ffmt); - v4l_bound_align_image(width, min_w, max_w, - ffs(var->min_out_pixsize) - 1, - height, min_h, FIMC_CAMIF_MAX_HEIGHT, - align_h, - 64/(ALIGN(depth, 8))); - - dbg("pad%d: code: 0x%x, %dx%d. dst fmt: %dx%d", - pad, code ? *code : 0, *width, *height, - dst->f_width, dst->f_height); - - return ffmt; -} - -static void fimc_capture_try_crop(struct fimc_ctx *ctx, struct v4l2_rect *r, - int pad) -{ - bool rotate = ctx->rotation == 90 || ctx->rotation == 270; - struct fimc_dev *fimc = ctx->fimc_dev; - struct samsung_fimc_variant *var = fimc->variant; - struct fimc_pix_limit *pl = var->pix_limit; - struct fimc_frame *sink = &ctx->s_frame; - u32 max_w, max_h, min_w = 0, min_h = 0, min_sz; - u32 align_sz = 0, align_h = 4; - u32 max_sc_h, max_sc_v; - - /* In JPEG transparent transfer mode cropping is not supported */ - if (fimc_fmt_is_jpeg(ctx->d_frame.fmt->color)) { - r->width = sink->f_width; - r->height = sink->f_height; - r->left = r->top = 0; - return; - } - if (pad == FIMC_SD_PAD_SOURCE) { - if (ctx->rotation != 90 && ctx->rotation != 270) - align_h = 1; - max_sc_h = min(SCALER_MAX_HRATIO, 1 << (ffs(sink->width) - 3)); - max_sc_v = min(SCALER_MAX_VRATIO, 1 << (ffs(sink->height) - 1)); - min_sz = var->min_out_pixsize; - } else { - u32 depth = fimc_get_format_depth(sink->fmt); - align_sz = 64/ALIGN(depth, 8); - min_sz = var->min_inp_pixsize; - min_w = min_h = min_sz; - max_sc_h = max_sc_v = 1; - } - /* - * For the crop rectangle at source pad the following constraints - * must be met: - * - it must fit in the sink pad format rectangle (f_width/f_height); - * - maximum downscaling ratio is 64; - * - maximum crop size depends if the rotator is used or not; - * - the sink pad format width/height must be 4 multiple of the - * prescaler ratios determined by sink pad size and source pad crop, - * the prescaler ratio is returned by fimc_get_scaler_factor(). - */ - max_w = min_t(u32, - rotate ? pl->out_rot_en_w : pl->out_rot_dis_w, - rotate ? sink->f_height : sink->f_width); - max_h = min_t(u32, FIMC_CAMIF_MAX_HEIGHT, sink->f_height); - if (pad == FIMC_SD_PAD_SOURCE) { - min_w = min_t(u32, max_w, sink->f_width / max_sc_h); - min_h = min_t(u32, max_h, sink->f_height / max_sc_v); - if (rotate) { - swap(max_sc_h, max_sc_v); - swap(min_w, min_h); - } - } - v4l_bound_align_image(&r->width, min_w, max_w, ffs(min_sz) - 1, - &r->height, min_h, max_h, align_h, - align_sz); - /* Adjust left/top if cropping rectangle is out of bounds */ - r->left = clamp_t(u32, r->left, 0, sink->f_width - r->width); - r->top = clamp_t(u32, r->top, 0, sink->f_height - r->height); - r->left = round_down(r->left, var->hor_offs_align); - - dbg("pad%d: (%d,%d)/%dx%d, sink fmt: %dx%d", - pad, r->left, r->top, r->width, r->height, - sink->f_width, sink->f_height); -} - -/* - * The video node ioctl operations - */ -static int fimc_vidioc_querycap_capture(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct fimc_dev *fimc = video_drvdata(file); - - strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1); - strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1); - cap->bus_info[0] = 0; - cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE; - - return 0; -} - -static int fimc_cap_enum_fmt_mplane(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct fimc_fmt *fmt; - - fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM | FMT_FLAGS_M2M, - f->index); - if (!fmt) - return -EINVAL; - strncpy(f->description, fmt->name, sizeof(f->description) - 1); - f->pixelformat = fmt->fourcc; - if (fmt->fourcc == V4L2_MBUS_FMT_JPEG_1X8) - f->flags |= V4L2_FMT_FLAG_COMPRESSED; - return 0; -} - -/** - * fimc_pipeline_try_format - negotiate and/or set formats at pipeline - * elements - * @ctx: FIMC capture context - * @tfmt: media bus format to try/set on subdevs - * @fmt_id: fimc pixel format id corresponding to returned @tfmt (output) - * @set: true to set format on subdevs, false to try only - */ -static int fimc_pipeline_try_format(struct fimc_ctx *ctx, - struct v4l2_mbus_framefmt *tfmt, - struct fimc_fmt **fmt_id, - bool set) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - struct v4l2_subdev *sd = fimc->pipeline.sensor; - struct v4l2_subdev *csis = fimc->pipeline.csis; - struct v4l2_subdev_format sfmt; - struct v4l2_mbus_framefmt *mf = &sfmt.format; - struct fimc_fmt *ffmt = NULL; - int ret, i = 0; - - if (WARN_ON(!sd || !tfmt)) - return -EINVAL; - - memset(&sfmt, 0, sizeof(sfmt)); - sfmt.format = *tfmt; - - sfmt.which = set ? V4L2_SUBDEV_FORMAT_ACTIVE : V4L2_SUBDEV_FORMAT_TRY; - while (1) { - ffmt = fimc_find_format(NULL, mf->code != 0 ? &mf->code : NULL, - FMT_FLAGS_CAM, i++); - if (ffmt == NULL) { - /* - * Notify user-space if common pixel code for - * host and sensor does not exist. - */ - return -EINVAL; - } - mf->code = tfmt->code = ffmt->mbus_code; - - ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt); - if (ret) - return ret; - if (mf->code != tfmt->code) { - mf->code = 0; - continue; - } - if (mf->width != tfmt->width || mf->height != tfmt->height) { - u32 fcc = ffmt->fourcc; - tfmt->width = mf->width; - tfmt->height = mf->height; - ffmt = fimc_capture_try_format(ctx, - &tfmt->width, &tfmt->height, - NULL, &fcc, FIMC_SD_PAD_SOURCE); - if (ffmt && ffmt->mbus_code) - mf->code = ffmt->mbus_code; - if (mf->width != tfmt->width || - mf->height != tfmt->height) - continue; - tfmt->code = mf->code; - } - if (csis) - ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt); - - if (mf->code == tfmt->code && - mf->width == tfmt->width && mf->height == tfmt->height) - break; - } - - if (fmt_id && ffmt) - *fmt_id = ffmt; - *tfmt = *mf; - - dbg("code: 0x%x, %dx%d, %p", mf->code, mf->width, mf->height, ffmt); - return 0; -} - -static int fimc_cap_g_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return -EINVAL; - - return fimc_fill_format(&ctx->d_frame, f); -} - -static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct v4l2_mbus_framefmt mf; - struct fimc_fmt *ffmt = NULL; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return -EINVAL; - - if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { - fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SINK); - ctx->s_frame.f_width = pix->width; - ctx->s_frame.f_height = pix->height; - } - ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SOURCE); - if (!ffmt) - return -EINVAL; - - if (!fimc->vid_cap.user_subdev_api) { - mf.width = pix->width; - mf.height = pix->height; - mf.code = ffmt->mbus_code; - fimc_md_graph_lock(fimc); - fimc_pipeline_try_format(ctx, &mf, &ffmt, false); - fimc_md_graph_unlock(fimc); - - pix->width = mf.width; - pix->height = mf.height; - if (ffmt) - pix->pixelformat = ffmt->fourcc; - } - - fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix); - return 0; -} - -static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, bool jpeg) -{ - ctx->scaler.enabled = !jpeg; - fimc_ctrls_activate(ctx, !jpeg); - - if (jpeg) - set_bit(ST_CAPT_JPEG, &ctx->fimc_dev->state); - else - clear_bit(ST_CAPT_JPEG, &ctx->fimc_dev->state); -} - -static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f) -{ - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.mf; - struct fimc_frame *ff = &ctx->d_frame; - struct fimc_fmt *s_fmt = NULL; - int ret, i; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return -EINVAL; - if (vb2_is_busy(&fimc->vid_cap.vbq)) - return -EBUSY; - - /* Pre-configure format at camera interface input, for JPEG only */ - if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { - fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SINK); - ctx->s_frame.f_width = pix->width; - ctx->s_frame.f_height = pix->height; - } - /* Try the format at the scaler and the DMA output */ - ff->fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SOURCE); - if (!ff->fmt) - return -EINVAL; - - /* Update RGB Alpha control state and value range */ - fimc_alpha_ctrl_update(ctx); - - /* Try to match format at the host and the sensor */ - if (!fimc->vid_cap.user_subdev_api) { - mf->code = ff->fmt->mbus_code; - mf->width = pix->width; - mf->height = pix->height; - - fimc_md_graph_lock(fimc); - ret = fimc_pipeline_try_format(ctx, mf, &s_fmt, true); - fimc_md_graph_unlock(fimc); - if (ret) - return ret; - pix->width = mf->width; - pix->height = mf->height; - } - fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix); - for (i = 0; i < ff->fmt->colplanes; i++) - ff->payload[i] = - (pix->width * pix->height * ff->fmt->depth[i]) / 8; - - set_frame_bounds(ff, pix->width, pix->height); - /* Reset the composition rectangle if not yet configured */ - if (!(ctx->state & FIMC_DST_CROP)) - set_frame_crop(ff, 0, 0, pix->width, pix->height); - - fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ff->fmt->color)); - - /* Reset cropping and set format at the camera interface input */ - if (!fimc->vid_cap.user_subdev_api) { - ctx->s_frame.fmt = s_fmt; - set_frame_bounds(&ctx->s_frame, pix->width, pix->height); - set_frame_crop(&ctx->s_frame, 0, 0, pix->width, pix->height); - } - - return ret; -} - -static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct fimc_dev *fimc = video_drvdata(file); - - return fimc_capture_set_format(fimc, f); -} - -static int fimc_cap_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct v4l2_subdev *sd = fimc->pipeline.sensor; - - if (i->index != 0) - return -EINVAL; - - i->type = V4L2_INPUT_TYPE_CAMERA; - if (sd) - strlcpy(i->name, sd->name, sizeof(i->name)); - return 0; -} - -static int fimc_cap_s_input(struct file *file, void *priv, unsigned int i) -{ - return i == 0 ? i : -EINVAL; -} - -static int fimc_cap_g_input(struct file *file, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -/** - * fimc_pipeline_validate - check for formats inconsistencies - * between source and sink pad of each link - * - * Return 0 if all formats match or -EPIPE otherwise. - */ -static int fimc_pipeline_validate(struct fimc_dev *fimc) -{ - struct v4l2_subdev_format sink_fmt, src_fmt; - struct fimc_vid_cap *vid_cap = &fimc->vid_cap; - struct v4l2_subdev *sd; - struct media_pad *pad; - int ret; - - /* Start with the video capture node pad */ - pad = media_entity_remote_source(&vid_cap->vd_pad); - if (pad == NULL) - return -EPIPE; - /* FIMC.{N} subdevice */ - sd = media_entity_to_v4l2_subdev(pad->entity); - - while (1) { - /* Retrieve format at the sink pad */ - pad = &sd->entity.pads[0]; - if (!(pad->flags & MEDIA_PAD_FL_SINK)) - break; - /* Don't call FIMC subdev operation to avoid nested locking */ - if (sd == fimc->vid_cap.subdev) { - struct fimc_frame *ff = &vid_cap->ctx->s_frame; - sink_fmt.format.width = ff->f_width; - sink_fmt.format.height = ff->f_height; - sink_fmt.format.code = ff->fmt ? ff->fmt->mbus_code : 0; - } else { - sink_fmt.pad = pad->index; - sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sink_fmt); - if (ret < 0 && ret != -ENOIOCTLCMD) - return -EPIPE; - } - /* Retrieve format at the source pad */ - pad = media_entity_remote_source(pad); - if (pad == NULL || - media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) - break; - - sd = media_entity_to_v4l2_subdev(pad->entity); - src_fmt.pad = pad->index; - src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt); - if (ret < 0 && ret != -ENOIOCTLCMD) - return -EPIPE; - - if (src_fmt.format.width != sink_fmt.format.width || - src_fmt.format.height != sink_fmt.format.height || - src_fmt.format.code != sink_fmt.format.code) - return -EPIPE; - } - return 0; -} - -static int fimc_cap_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_pipeline *p = &fimc->pipeline; - int ret; - - if (fimc_capture_active(fimc)) - return -EBUSY; - - media_entity_pipeline_start(&p->sensor->entity, p->pipe); - - if (fimc->vid_cap.user_subdev_api) { - ret = fimc_pipeline_validate(fimc); - if (ret) - return ret; - } - return vb2_streamon(&fimc->vid_cap.vbq, type); -} - -static int fimc_cap_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct v4l2_subdev *sd = fimc->pipeline.sensor; - int ret; - - ret = vb2_streamoff(&fimc->vid_cap.vbq, type); - if (ret == 0) - media_entity_pipeline_stop(&sd->entity); - return ret; -} - -static int fimc_cap_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) -{ - struct fimc_dev *fimc = video_drvdata(file); - int ret = vb2_reqbufs(&fimc->vid_cap.vbq, reqbufs); - - if (!ret) - fimc->vid_cap.reqbufs_count = reqbufs->count; - return ret; -} - -static int fimc_cap_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct fimc_dev *fimc = video_drvdata(file); - - return vb2_querybuf(&fimc->vid_cap.vbq, buf); -} - -static int fimc_cap_qbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct fimc_dev *fimc = video_drvdata(file); - - return vb2_qbuf(&fimc->vid_cap.vbq, buf); -} - -static int fimc_cap_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct fimc_dev *fimc = video_drvdata(file); - - return vb2_dqbuf(&fimc->vid_cap.vbq, buf, file->f_flags & O_NONBLOCK); -} - -static int fimc_cap_create_bufs(struct file *file, void *priv, - struct v4l2_create_buffers *create) -{ - struct fimc_dev *fimc = video_drvdata(file); - - return vb2_create_bufs(&fimc->vid_cap.vbq, create); -} - -static int fimc_cap_prepare_buf(struct file *file, void *priv, - struct v4l2_buffer *b) -{ - struct fimc_dev *fimc = video_drvdata(file); - - return vb2_prepare_buf(&fimc->vid_cap.vbq, b); -} - -static int fimc_cap_g_selection(struct file *file, void *fh, - struct v4l2_selection *s) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct fimc_frame *f = &ctx->s_frame; - - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return -EINVAL; - - switch (s->target) { - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - f = &ctx->d_frame; - case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: - s->r.left = 0; - s->r.top = 0; - s->r.width = f->o_width; - s->r.height = f->o_height; - return 0; - - case V4L2_SEL_TGT_COMPOSE_ACTIVE: - f = &ctx->d_frame; - case V4L2_SEL_TGT_CROP_ACTIVE: - s->r.left = f->offs_h; - s->r.top = f->offs_v; - s->r.width = f->width; - s->r.height = f->height; - return 0; - } - - return -EINVAL; -} - -/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */ -int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b) -{ - if (a->left < b->left || a->top < b->top) - return 0; - if (a->left + a->width > b->left + b->width) - return 0; - if (a->top + a->height > b->top + b->height) - return 0; - - return 1; -} - -static int fimc_cap_s_selection(struct file *file, void *fh, - struct v4l2_selection *s) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct v4l2_rect rect = s->r; - struct fimc_frame *f; - unsigned long flags; - unsigned int pad; - - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return -EINVAL; - - switch (s->target) { - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - case V4L2_SEL_TGT_COMPOSE_ACTIVE: - f = &ctx->d_frame; - pad = FIMC_SD_PAD_SOURCE; - break; - case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: - case V4L2_SEL_TGT_CROP_ACTIVE: - f = &ctx->s_frame; - pad = FIMC_SD_PAD_SINK; - break; - default: - return -EINVAL; - } - - fimc_capture_try_crop(ctx, &rect, pad); - - if (s->flags & V4L2_SEL_FLAG_LE && - !enclosed_rectangle(&rect, &s->r)) - return -ERANGE; - - if (s->flags & V4L2_SEL_FLAG_GE && - !enclosed_rectangle(&s->r, &rect)) - return -ERANGE; - - s->r = rect; - spin_lock_irqsave(&fimc->slock, flags); - set_frame_crop(f, s->r.left, s->r.top, s->r.width, - s->r.height); - spin_unlock_irqrestore(&fimc->slock, flags); - - set_bit(ST_CAPT_APPLY_CFG, &fimc->state); - return 0; -} - -static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = { - .vidioc_querycap = fimc_vidioc_querycap_capture, - - .vidioc_enum_fmt_vid_cap_mplane = fimc_cap_enum_fmt_mplane, - .vidioc_try_fmt_vid_cap_mplane = fimc_cap_try_fmt_mplane, - .vidioc_s_fmt_vid_cap_mplane = fimc_cap_s_fmt_mplane, - .vidioc_g_fmt_vid_cap_mplane = fimc_cap_g_fmt_mplane, - - .vidioc_reqbufs = fimc_cap_reqbufs, - .vidioc_querybuf = fimc_cap_querybuf, - - .vidioc_qbuf = fimc_cap_qbuf, - .vidioc_dqbuf = fimc_cap_dqbuf, - - .vidioc_prepare_buf = fimc_cap_prepare_buf, - .vidioc_create_bufs = fimc_cap_create_bufs, - - .vidioc_streamon = fimc_cap_streamon, - .vidioc_streamoff = fimc_cap_streamoff, - - .vidioc_g_selection = fimc_cap_g_selection, - .vidioc_s_selection = fimc_cap_s_selection, - - .vidioc_enum_input = fimc_cap_enum_input, - .vidioc_s_input = fimc_cap_s_input, - .vidioc_g_input = fimc_cap_g_input, -}; - -/* Capture subdev media entity operations */ -static int fimc_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - - if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) - return -EINVAL; - - if (WARN_ON(fimc == NULL)) - return 0; - - dbg("%s --> %s, flags: 0x%x. input: 0x%x", - local->entity->name, remote->entity->name, flags, - fimc->vid_cap.input); - - if (flags & MEDIA_LNK_FL_ENABLED) { - if (fimc->vid_cap.input != 0) - return -EBUSY; - fimc->vid_cap.input = sd->grp_id; - return 0; - } - - fimc->vid_cap.input = 0; - return 0; -} - -static const struct media_entity_operations fimc_sd_media_ops = { - .link_setup = fimc_link_setup, -}; - -/** - * fimc_sensor_notify - v4l2_device notification from a sensor subdev - * @sd: pointer to a subdev generating the notification - * @notification: the notification type, must be S5P_FIMC_TX_END_NOTIFY - * @arg: pointer to an u32 type integer that stores the frame payload value - * - * The End Of Frame notification sent by sensor subdev in its still capture - * mode. If there is only a single VSYNC generated by the sensor at the - * beginning of a frame transmission, FIMC does not issue the LastIrq - * (end of frame) interrupt. And this notification is used to complete the - * frame capture and returning a buffer to user-space. Subdev drivers should - * call this notification from their last 'End of frame capture' interrupt. - */ -void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification, - void *arg) -{ - struct fimc_sensor_info *sensor; - struct fimc_vid_buffer *buf; - struct fimc_md *fmd; - struct fimc_dev *fimc; - unsigned long flags; - - if (sd == NULL) - return; - - sensor = v4l2_get_subdev_hostdata(sd); - fmd = entity_to_fimc_mdev(&sd->entity); - - spin_lock_irqsave(&fmd->slock, flags); - fimc = sensor ? sensor->host : NULL; - - if (fimc && arg && notification == S5P_FIMC_TX_END_NOTIFY && - test_bit(ST_CAPT_PEND, &fimc->state)) { - unsigned long irq_flags; - spin_lock_irqsave(&fimc->slock, irq_flags); - if (!list_empty(&fimc->vid_cap.active_buf_q)) { - buf = list_entry(fimc->vid_cap.active_buf_q.next, - struct fimc_vid_buffer, list); - vb2_set_plane_payload(&buf->vb, 0, *((u32 *)arg)); - } - fimc_capture_irq_handler(fimc, true); - fimc_deactivate_capture(fimc); - spin_unlock_irqrestore(&fimc->slock, irq_flags); - } - spin_unlock_irqrestore(&fmd->slock, flags); -} - -static int fimc_subdev_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_mbus_code_enum *code) -{ - struct fimc_fmt *fmt; - - fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, code->index); - if (!fmt) - return -EINVAL; - code->code = fmt->mbus_code; - return 0; -} - -static int fimc_subdev_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_format *fmt) -{ - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct v4l2_mbus_framefmt *mf; - struct fimc_frame *ff; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = v4l2_subdev_get_try_format(fh, fmt->pad); - fmt->format = *mf; - return 0; - } - mf = &fmt->format; - mf->colorspace = V4L2_COLORSPACE_JPEG; - ff = fmt->pad == FIMC_SD_PAD_SINK ? &ctx->s_frame : &ctx->d_frame; - - mutex_lock(&fimc->lock); - /* The pixel code is same on both input and output pad */ - if (!WARN_ON(ctx->s_frame.fmt == NULL)) - mf->code = ctx->s_frame.fmt->mbus_code; - mf->width = ff->f_width; - mf->height = ff->f_height; - mutex_unlock(&fimc->lock); - - return 0; -} - -static int fimc_subdev_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_format *fmt) -{ - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *mf = &fmt->format; - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct fimc_frame *ff; - struct fimc_fmt *ffmt; - - dbg("pad%d: code: 0x%x, %dx%d", - fmt->pad, mf->code, mf->width, mf->height); - - if (fmt->pad == FIMC_SD_PAD_SOURCE && - vb2_is_busy(&fimc->vid_cap.vbq)) - return -EBUSY; - - mutex_lock(&fimc->lock); - ffmt = fimc_capture_try_format(ctx, &mf->width, &mf->height, - &mf->code, NULL, fmt->pad); - mutex_unlock(&fimc->lock); - mf->colorspace = V4L2_COLORSPACE_JPEG; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = v4l2_subdev_get_try_format(fh, fmt->pad); - *mf = fmt->format; - return 0; - } - /* Update RGB Alpha control state and value range */ - fimc_alpha_ctrl_update(ctx); - - fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color)); - - ff = fmt->pad == FIMC_SD_PAD_SINK ? - &ctx->s_frame : &ctx->d_frame; - - mutex_lock(&fimc->lock); - set_frame_bounds(ff, mf->width, mf->height); - fimc->vid_cap.mf = *mf; - ff->fmt = ffmt; - - /* Reset the crop rectangle if required. */ - if (!(fmt->pad == FIMC_SD_PAD_SOURCE && (ctx->state & FIMC_DST_CROP))) - set_frame_crop(ff, 0, 0, mf->width, mf->height); - - if (fmt->pad == FIMC_SD_PAD_SINK) - ctx->state &= ~FIMC_DST_CROP; - mutex_unlock(&fimc->lock); - return 0; -} - -static int fimc_subdev_get_crop(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) -{ - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct v4l2_rect *r = &crop->rect; - struct fimc_frame *ff; - - if (crop->which == V4L2_SUBDEV_FORMAT_TRY) { - crop->rect = *v4l2_subdev_get_try_crop(fh, crop->pad); - return 0; - } - ff = crop->pad == FIMC_SD_PAD_SINK ? - &ctx->s_frame : &ctx->d_frame; - - mutex_lock(&fimc->lock); - r->left = ff->offs_h; - r->top = ff->offs_v; - r->width = ff->width; - r->height = ff->height; - mutex_unlock(&fimc->lock); - - dbg("ff:%p, pad%d: l:%d, t:%d, %dx%d, f_w: %d, f_h: %d", - ff, crop->pad, r->left, r->top, r->width, r->height, - ff->f_width, ff->f_height); - - return 0; -} - -static int fimc_subdev_set_crop(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) -{ - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct v4l2_rect *r = &crop->rect; - struct fimc_frame *ff; - unsigned long flags; - - dbg("(%d,%d)/%dx%d", r->left, r->top, r->width, r->height); - - ff = crop->pad == FIMC_SD_PAD_SOURCE ? - &ctx->d_frame : &ctx->s_frame; - - mutex_lock(&fimc->lock); - fimc_capture_try_crop(ctx, r, crop->pad); - - if (crop->which == V4L2_SUBDEV_FORMAT_TRY) { - mutex_unlock(&fimc->lock); - *v4l2_subdev_get_try_crop(fh, crop->pad) = *r; - return 0; - } - spin_lock_irqsave(&fimc->slock, flags); - set_frame_crop(ff, r->left, r->top, r->width, r->height); - if (crop->pad == FIMC_SD_PAD_SOURCE) - ctx->state |= FIMC_DST_CROP; - - set_bit(ST_CAPT_APPLY_CFG, &fimc->state); - spin_unlock_irqrestore(&fimc->slock, flags); - - dbg("pad%d: (%d,%d)/%dx%d", crop->pad, r->left, r->top, - r->width, r->height); - - mutex_unlock(&fimc->lock); - return 0; -} - -static struct v4l2_subdev_pad_ops fimc_subdev_pad_ops = { - .enum_mbus_code = fimc_subdev_enum_mbus_code, - .get_fmt = fimc_subdev_get_fmt, - .set_fmt = fimc_subdev_set_fmt, - .get_crop = fimc_subdev_get_crop, - .set_crop = fimc_subdev_set_crop, -}; - -static struct v4l2_subdev_ops fimc_subdev_ops = { - .pad = &fimc_subdev_pad_ops, -}; - -static int fimc_create_capture_subdev(struct fimc_dev *fimc, - struct v4l2_device *v4l2_dev) -{ - struct v4l2_subdev *sd; - int ret; - - sd = kzalloc(sizeof(*sd), GFP_KERNEL); - if (!sd) - return -ENOMEM; - - v4l2_subdev_init(sd, &fimc_subdev_ops); - sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; - snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id); - - fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM, - fimc->vid_cap.sd_pads, 0); - if (ret) - goto me_err; - ret = v4l2_device_register_subdev(v4l2_dev, sd); - if (ret) - goto sd_err; - - fimc->vid_cap.subdev = sd; - v4l2_set_subdevdata(sd, fimc); - sd->entity.ops = &fimc_sd_media_ops; - return 0; -sd_err: - media_entity_cleanup(&sd->entity); -me_err: - kfree(sd); - return ret; -} - -static void fimc_destroy_capture_subdev(struct fimc_dev *fimc) -{ - struct v4l2_subdev *sd = fimc->vid_cap.subdev; - - if (!sd) - return; - media_entity_cleanup(&sd->entity); - v4l2_device_unregister_subdev(sd); - kfree(sd); - fimc->vid_cap.subdev = NULL; -} - -/* Set default format at the sensor and host interface */ -static int fimc_capture_set_default_format(struct fimc_dev *fimc) -{ - struct v4l2_format fmt = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - .fmt.pix_mp = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_YUYV, - .field = V4L2_FIELD_NONE, - .colorspace = V4L2_COLORSPACE_JPEG, - }, - }; - - return fimc_capture_set_format(fimc, &fmt); -} - -/* fimc->lock must be already initialized */ -int fimc_register_capture_device(struct fimc_dev *fimc, - struct v4l2_device *v4l2_dev) -{ - struct video_device *vfd; - struct fimc_vid_cap *vid_cap; - struct fimc_ctx *ctx; - struct vb2_queue *q; - int ret = -ENOMEM; - - ctx = kzalloc(sizeof *ctx, GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - ctx->fimc_dev = fimc; - ctx->in_path = FIMC_CAMERA; - ctx->out_path = FIMC_DMA; - ctx->state = FIMC_CTX_CAP; - ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); - ctx->d_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); - - vfd = video_device_alloc(); - if (!vfd) { - v4l2_err(v4l2_dev, "Failed to allocate video device\n"); - goto err_vd_alloc; - } - - snprintf(vfd->name, sizeof(vfd->name), "%s.capture", - dev_name(&fimc->pdev->dev)); - - vfd->fops = &fimc_capture_fops; - vfd->ioctl_ops = &fimc_capture_ioctl_ops; - vfd->v4l2_dev = v4l2_dev; - vfd->minor = -1; - vfd->release = video_device_release; - vfd->lock = &fimc->lock; - video_set_drvdata(vfd, fimc); - - vid_cap = &fimc->vid_cap; - vid_cap->vfd = vfd; - vid_cap->active_buf_cnt = 0; - vid_cap->reqbufs_count = 0; - vid_cap->refcnt = 0; - - INIT_LIST_HEAD(&vid_cap->pending_buf_q); - INIT_LIST_HEAD(&vid_cap->active_buf_q); - spin_lock_init(&ctx->slock); - vid_cap->ctx = ctx; - - q = &fimc->vid_cap.vbq; - memset(q, 0, sizeof(*q)); - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - q->io_modes = VB2_MMAP | VB2_USERPTR; - q->drv_priv = fimc->vid_cap.ctx; - q->ops = &fimc_capture_qops; - q->mem_ops = &vb2_dma_contig_memops; - q->buf_struct_size = sizeof(struct fimc_vid_buffer); - - vb2_queue_init(q); - - fimc->vid_cap.vd_pad.flags = MEDIA_PAD_FL_SINK; - ret = media_entity_init(&vfd->entity, 1, &fimc->vid_cap.vd_pad, 0); - if (ret) - goto err_ent; - ret = fimc_create_capture_subdev(fimc, v4l2_dev); - if (ret) - goto err_sd_reg; - - vfd->ctrl_handler = &ctx->ctrl_handler; - return 0; - -err_sd_reg: - media_entity_cleanup(&vfd->entity); -err_ent: - video_device_release(vfd); -err_vd_alloc: - kfree(ctx); - return ret; -} - -void fimc_unregister_capture_device(struct fimc_dev *fimc) -{ - struct video_device *vfd = fimc->vid_cap.vfd; - - if (vfd) { - media_entity_cleanup(&vfd->entity); - /* Can also be called if video device was - not registered */ - video_unregister_device(vfd); - } - fimc_destroy_capture_subdev(fimc); - kfree(fimc->vid_cap.ctx); - fimc->vid_cap.ctx = NULL; -} diff --git a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-core.c b/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-core.c deleted file mode 100644 index e09ba7b0..00000000 --- a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-core.c +++ /dev/null @@ -1,2045 +0,0 @@ -/* - * Samsung S5P/EXYNOS4 SoC series camera interface (video postprocessor) driver - * - * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd. - * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 2 of the License, - * or (at your option) any later version. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/bug.h> -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/list.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/clk.h> -#include <media/v4l2-ioctl.h> -#include <media/videobuf2-core.h> -#include <media/videobuf2-dma-contig.h> - -#include "fimc-core.h" -#include "fimc-mdevice.h" - -static char *fimc_clocks[MAX_FIMC_CLOCKS] = { - "sclk_fimc", "fimc" -}; - -static struct fimc_fmt fimc_formats[] = { - { - .name = "RGB565", - .fourcc = V4L2_PIX_FMT_RGB565, - .depth = { 16 }, - .color = S5P_FIMC_RGB565, - .memplanes = 1, - .colplanes = 1, - .flags = FMT_FLAGS_M2M, - }, { - .name = "BGR666", - .fourcc = V4L2_PIX_FMT_BGR666, - .depth = { 32 }, - .color = S5P_FIMC_RGB666, - .memplanes = 1, - .colplanes = 1, - .flags = FMT_FLAGS_M2M, - }, { - .name = "ARGB8888, 32 bpp", - .fourcc = V4L2_PIX_FMT_RGB32, - .depth = { 32 }, - .color = S5P_FIMC_RGB888, - .memplanes = 1, - .colplanes = 1, - .flags = FMT_FLAGS_M2M | FMT_HAS_ALPHA, - }, { - .name = "ARGB1555", - .fourcc = V4L2_PIX_FMT_RGB555, - .depth = { 16 }, - .color = S5P_FIMC_RGB555, - .memplanes = 1, - .colplanes = 1, - .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA, - }, { - .name = "ARGB4444", - .fourcc = V4L2_PIX_FMT_RGB444, - .depth = { 16 }, - .color = S5P_FIMC_RGB444, - .memplanes = 1, - .colplanes = 1, - .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA, - }, { - .name = "YUV 4:2:2 packed, YCbYCr", - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = { 16 }, - .color = S5P_FIMC_YCBYCR422, - .memplanes = 1, - .colplanes = 1, - .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, - .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, - }, { - .name = "YUV 4:2:2 packed, CbYCrY", - .fourcc = V4L2_PIX_FMT_UYVY, - .depth = { 16 }, - .color = S5P_FIMC_CBYCRY422, - .memplanes = 1, - .colplanes = 1, - .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, - .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, - }, { - .name = "YUV 4:2:2 packed, CrYCbY", - .fourcc = V4L2_PIX_FMT_VYUY, - .depth = { 16 }, - .color = S5P_FIMC_CRYCBY422, - .memplanes = 1, - .colplanes = 1, - .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8, - .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, - }, { - .name = "YUV 4:2:2 packed, YCrYCb", - .fourcc = V4L2_PIX_FMT_YVYU, - .depth = { 16 }, - .color = S5P_FIMC_YCRYCB422, - .memplanes = 1, - .colplanes = 1, - .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8, - .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, - }, { - .name = "YUV 4:2:2 planar, Y/Cb/Cr", - .fourcc = V4L2_PIX_FMT_YUV422P, - .depth = { 12 }, - .color = S5P_FIMC_YCBYCR422, - .memplanes = 1, - .colplanes = 3, - .flags = FMT_FLAGS_M2M, - }, { - .name = "YUV 4:2:2 planar, Y/CbCr", - .fourcc = V4L2_PIX_FMT_NV16, - .depth = { 16 }, - .color = S5P_FIMC_YCBYCR422, - .memplanes = 1, - .colplanes = 2, - .flags = FMT_FLAGS_M2M, - }, { - .name = "YUV 4:2:2 planar, Y/CrCb", - .fourcc = V4L2_PIX_FMT_NV61, - .depth = { 16 }, - .color = S5P_FIMC_YCRYCB422, - .memplanes = 1, - .colplanes = 2, - .flags = FMT_FLAGS_M2M, - }, { - .name = "YUV 4:2:0 planar, YCbCr", - .fourcc = V4L2_PIX_FMT_YUV420, - .depth = { 12 }, - .color = S5P_FIMC_YCBCR420, - .memplanes = 1, - .colplanes = 3, - .flags = FMT_FLAGS_M2M, - }, { - .name = "YUV 4:2:0 planar, Y/CbCr", - .fourcc = V4L2_PIX_FMT_NV12, - .depth = { 12 }, - .color = S5P_FIMC_YCBCR420, - .memplanes = 1, - .colplanes = 2, - .flags = FMT_FLAGS_M2M, - }, { - .name = "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr", - .fourcc = V4L2_PIX_FMT_NV12M, - .color = S5P_FIMC_YCBCR420, - .depth = { 8, 4 }, - .memplanes = 2, - .colplanes = 2, - .flags = FMT_FLAGS_M2M, - }, { - .name = "YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr", - .fourcc = V4L2_PIX_FMT_YUV420M, - .color = S5P_FIMC_YCBCR420, - .depth = { 8, 2, 2 }, - .memplanes = 3, - .colplanes = 3, - .flags = FMT_FLAGS_M2M, - }, { - .name = "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled", - .fourcc = V4L2_PIX_FMT_NV12MT, - .color = S5P_FIMC_YCBCR420, - .depth = { 8, 4 }, - .memplanes = 2, - .colplanes = 2, - .flags = FMT_FLAGS_M2M, - }, { - .name = "JPEG encoded data", - .fourcc = V4L2_PIX_FMT_JPEG, - .color = S5P_FIMC_JPEG, - .depth = { 8 }, - .memplanes = 1, - .colplanes = 1, - .mbus_code = V4L2_MBUS_FMT_JPEG_1X8, - .flags = FMT_FLAGS_CAM, - }, -}; - -static unsigned int get_m2m_fmt_flags(unsigned int stream_type) -{ - if (stream_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - return FMT_FLAGS_M2M_IN; - else - return FMT_FLAGS_M2M_OUT; -} - -int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh, - int dw, int dh, int rotation) -{ - if (rotation == 90 || rotation == 270) - swap(dw, dh); - - if (!ctx->scaler.enabled) - return (sw == dw && sh == dh) ? 0 : -EINVAL; - - if ((sw >= SCALER_MAX_HRATIO * dw) || (sh >= SCALER_MAX_VRATIO * dh)) - return -EINVAL; - - return 0; -} - -static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift) -{ - u32 sh = 6; - - if (src >= 64 * tar) - return -EINVAL; - - while (sh--) { - u32 tmp = 1 << sh; - if (src >= tar * tmp) { - *shift = sh, *ratio = tmp; - return 0; - } - } - *shift = 0, *ratio = 1; - return 0; -} - -int fimc_set_scaler_info(struct fimc_ctx *ctx) -{ - struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; - struct device *dev = &ctx->fimc_dev->pdev->dev; - struct fimc_scaler *sc = &ctx->scaler; - struct fimc_frame *s_frame = &ctx->s_frame; - struct fimc_frame *d_frame = &ctx->d_frame; - int tx, ty, sx, sy; - int ret; - - if (ctx->rotation == 90 || ctx->rotation == 270) { - ty = d_frame->width; - tx = d_frame->height; - } else { - tx = d_frame->width; - ty = d_frame->height; - } - if (tx <= 0 || ty <= 0) { - dev_err(dev, "Invalid target size: %dx%d", tx, ty); - return -EINVAL; - } - - sx = s_frame->width; - sy = s_frame->height; - if (sx <= 0 || sy <= 0) { - dev_err(dev, "Invalid source size: %dx%d", sx, sy); - return -EINVAL; - } - sc->real_width = sx; - sc->real_height = sy; - - ret = fimc_get_scaler_factor(sx, tx, &sc->pre_hratio, &sc->hfactor); - if (ret) - return ret; - - ret = fimc_get_scaler_factor(sy, ty, &sc->pre_vratio, &sc->vfactor); - if (ret) - return ret; - - sc->pre_dst_width = sx / sc->pre_hratio; - sc->pre_dst_height = sy / sc->pre_vratio; - - if (variant->has_mainscaler_ext) { - sc->main_hratio = (sx << 14) / (tx << sc->hfactor); - sc->main_vratio = (sy << 14) / (ty << sc->vfactor); - } else { - sc->main_hratio = (sx << 8) / (tx << sc->hfactor); - sc->main_vratio = (sy << 8) / (ty << sc->vfactor); - - } - - sc->scaleup_h = (tx >= sx) ? 1 : 0; - sc->scaleup_v = (ty >= sy) ? 1 : 0; - - /* check to see if input and output size/format differ */ - if (s_frame->fmt->color == d_frame->fmt->color - && s_frame->width == d_frame->width - && s_frame->height == d_frame->height) - sc->copy_mode = 1; - else - sc->copy_mode = 0; - - return 0; -} - -static void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state) -{ - struct vb2_buffer *src_vb, *dst_vb; - - if (!ctx || !ctx->m2m_ctx) - return; - - src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); - - if (src_vb && dst_vb) { - v4l2_m2m_buf_done(src_vb, vb_state); - v4l2_m2m_buf_done(dst_vb, vb_state); - v4l2_m2m_job_finish(ctx->fimc_dev->m2m.m2m_dev, - ctx->m2m_ctx); - } -} - -/* Complete the transaction which has been scheduled for execution. */ -static int fimc_m2m_shutdown(struct fimc_ctx *ctx) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - int ret; - - if (!fimc_m2m_pending(fimc)) - return 0; - - fimc_ctx_state_lock_set(FIMC_CTX_SHUT, ctx); - - ret = wait_event_timeout(fimc->irq_queue, - !fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx), - FIMC_SHUTDOWN_TIMEOUT); - - return ret == 0 ? -ETIMEDOUT : ret; -} - -static int start_streaming(struct vb2_queue *q, unsigned int count) -{ - struct fimc_ctx *ctx = q->drv_priv; - int ret; - - ret = pm_runtime_get_sync(&ctx->fimc_dev->pdev->dev); - return ret > 0 ? 0 : ret; -} - -static int stop_streaming(struct vb2_queue *q) -{ - struct fimc_ctx *ctx = q->drv_priv; - int ret; - - ret = fimc_m2m_shutdown(ctx); - if (ret == -ETIMEDOUT) - fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); - - pm_runtime_put(&ctx->fimc_dev->pdev->dev); - return 0; -} - -void fimc_capture_irq_handler(struct fimc_dev *fimc, bool final) -{ - struct fimc_vid_cap *cap = &fimc->vid_cap; - struct fimc_vid_buffer *v_buf; - struct timeval *tv; - struct timespec ts; - - if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) { - wake_up(&fimc->irq_queue); - return; - } - - if (!list_empty(&cap->active_buf_q) && - test_bit(ST_CAPT_RUN, &fimc->state) && final) { - ktime_get_real_ts(&ts); - - v_buf = fimc_active_queue_pop(cap); - - tv = &v_buf->vb.v4l2_buf.timestamp; - tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC; - v_buf->vb.v4l2_buf.sequence = cap->frame_count++; - - vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE); - } - - if (!list_empty(&cap->pending_buf_q)) { - - v_buf = fimc_pending_queue_pop(cap); - fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index); - v_buf->index = cap->buf_index; - - /* Move the buffer to the capture active queue */ - fimc_active_queue_add(cap, v_buf); - - dbg("next frame: %d, done frame: %d", - fimc_hw_get_frame_index(fimc), v_buf->index); - - if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) - cap->buf_index = 0; - } - - if (cap->active_buf_cnt == 0) { - if (final) - clear_bit(ST_CAPT_RUN, &fimc->state); - - if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) - cap->buf_index = 0; - } else { - set_bit(ST_CAPT_RUN, &fimc->state); - } - - fimc_capture_config_update(cap->ctx); - - dbg("frame: %d, active_buf_cnt: %d", - fimc_hw_get_frame_index(fimc), cap->active_buf_cnt); -} - -static irqreturn_t fimc_irq_handler(int irq, void *priv) -{ - struct fimc_dev *fimc = priv; - struct fimc_vid_cap *cap = &fimc->vid_cap; - struct fimc_ctx *ctx; - - fimc_hw_clear_irq(fimc); - - spin_lock(&fimc->slock); - - if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) { - if (test_and_clear_bit(ST_M2M_SUSPENDING, &fimc->state)) { - set_bit(ST_M2M_SUSPENDED, &fimc->state); - wake_up(&fimc->irq_queue); - goto out; - } - ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev); - if (ctx != NULL) { - spin_unlock(&fimc->slock); - fimc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE); - - spin_lock(&ctx->slock); - if (ctx->state & FIMC_CTX_SHUT) { - ctx->state &= ~FIMC_CTX_SHUT; - wake_up(&fimc->irq_queue); - } - spin_unlock(&ctx->slock); - } - return IRQ_HANDLED; - } else if (test_bit(ST_CAPT_PEND, &fimc->state)) { - fimc_capture_irq_handler(fimc, - !test_bit(ST_CAPT_JPEG, &fimc->state)); - if (cap->active_buf_cnt == 1) { - fimc_deactivate_capture(fimc); - clear_bit(ST_CAPT_STREAM, &fimc->state); - } - } -out: - spin_unlock(&fimc->slock); - return IRQ_HANDLED; -} - -/* The color format (colplanes, memplanes) must be already configured. */ -int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb, - struct fimc_frame *frame, struct fimc_addr *paddr) -{ - int ret = 0; - u32 pix_size; - - if (vb == NULL || frame == NULL) - return -EINVAL; - - pix_size = frame->width * frame->height; - - dbg("memplanes= %d, colplanes= %d, pix_size= %d", - frame->fmt->memplanes, frame->fmt->colplanes, pix_size); - - paddr->y = vb2_dma_contig_plane_dma_addr(vb, 0); - - if (frame->fmt->memplanes == 1) { - switch (frame->fmt->colplanes) { - case 1: - paddr->cb = 0; - paddr->cr = 0; - break; - case 2: - /* decompose Y into Y/Cb */ - paddr->cb = (u32)(paddr->y + pix_size); - paddr->cr = 0; - break; - case 3: - paddr->cb = (u32)(paddr->y + pix_size); - /* decompose Y into Y/Cb/Cr */ - if (S5P_FIMC_YCBCR420 == frame->fmt->color) - paddr->cr = (u32)(paddr->cb - + (pix_size >> 2)); - else /* 422 */ - paddr->cr = (u32)(paddr->cb - + (pix_size >> 1)); - break; - default: - return -EINVAL; - } - } else { - if (frame->fmt->memplanes >= 2) - paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1); - - if (frame->fmt->memplanes == 3) - paddr->cr = vb2_dma_contig_plane_dma_addr(vb, 2); - } - - dbg("PHYS_ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d", - paddr->y, paddr->cb, paddr->cr, ret); - - return ret; -} - -/* Set order for 1 and 2 plane YCBCR 4:2:2 formats. */ -void fimc_set_yuv_order(struct fimc_ctx *ctx) -{ - /* The one only mode supported in SoC. */ - ctx->in_order_2p = S5P_FIMC_LSB_CRCB; - ctx->out_order_2p = S5P_FIMC_LSB_CRCB; - - /* Set order for 1 plane input formats. */ - switch (ctx->s_frame.fmt->color) { - case S5P_FIMC_YCRYCB422: - ctx->in_order_1p = S5P_MSCTRL_ORDER422_CBYCRY; - break; - case S5P_FIMC_CBYCRY422: - ctx->in_order_1p = S5P_MSCTRL_ORDER422_YCRYCB; - break; - case S5P_FIMC_CRYCBY422: - ctx->in_order_1p = S5P_MSCTRL_ORDER422_YCBYCR; - break; - case S5P_FIMC_YCBYCR422: - default: - ctx->in_order_1p = S5P_MSCTRL_ORDER422_CRYCBY; - break; - } - dbg("ctx->in_order_1p= %d", ctx->in_order_1p); - - switch (ctx->d_frame.fmt->color) { - case S5P_FIMC_YCRYCB422: - ctx->out_order_1p = S5P_CIOCTRL_ORDER422_CBYCRY; - break; - case S5P_FIMC_CBYCRY422: - ctx->out_order_1p = S5P_CIOCTRL_ORDER422_YCRYCB; - break; - case S5P_FIMC_CRYCBY422: - ctx->out_order_1p = S5P_CIOCTRL_ORDER422_YCBYCR; - break; - case S5P_FIMC_YCBYCR422: - default: - ctx->out_order_1p = S5P_CIOCTRL_ORDER422_CRYCBY; - break; - } - dbg("ctx->out_order_1p= %d", ctx->out_order_1p); -} - -void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f) -{ - struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; - u32 i, depth = 0; - - for (i = 0; i < f->fmt->colplanes; i++) - depth += f->fmt->depth[i]; - - f->dma_offset.y_h = f->offs_h; - if (!variant->pix_hoff) - f->dma_offset.y_h *= (depth >> 3); - - f->dma_offset.y_v = f->offs_v; - - f->dma_offset.cb_h = f->offs_h; - f->dma_offset.cb_v = f->offs_v; - - f->dma_offset.cr_h = f->offs_h; - f->dma_offset.cr_v = f->offs_v; - - if (!variant->pix_hoff) { - if (f->fmt->colplanes == 3) { - f->dma_offset.cb_h >>= 1; - f->dma_offset.cr_h >>= 1; - } - if (f->fmt->color == S5P_FIMC_YCBCR420) { - f->dma_offset.cb_v >>= 1; - f->dma_offset.cr_v >>= 1; - } - } - - dbg("in_offset: color= %d, y_h= %d, y_v= %d", - f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v); -} - -/** - * fimc_prepare_config - check dimensions, operation and color mode - * and pre-calculate offset and the scaling coefficients. - * - * @ctx: hardware context information - * @flags: flags indicating which parameters to check/update - * - * Return: 0 if dimensions are valid or non zero otherwise. - */ -int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags) -{ - struct fimc_frame *s_frame, *d_frame; - struct vb2_buffer *vb = NULL; - int ret = 0; - - s_frame = &ctx->s_frame; - d_frame = &ctx->d_frame; - - if (flags & FIMC_PARAMS) { - /* Prepare the DMA offset ratios for scaler. */ - fimc_prepare_dma_offset(ctx, &ctx->s_frame); - fimc_prepare_dma_offset(ctx, &ctx->d_frame); - - if (s_frame->height > (SCALER_MAX_VRATIO * d_frame->height) || - s_frame->width > (SCALER_MAX_HRATIO * d_frame->width)) { - err("out of scaler range"); - return -EINVAL; - } - fimc_set_yuv_order(ctx); - } - - if (flags & FIMC_SRC_ADDR) { - vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); - ret = fimc_prepare_addr(ctx, vb, s_frame, &s_frame->paddr); - if (ret) - return ret; - } - - if (flags & FIMC_DST_ADDR) { - vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); - ret = fimc_prepare_addr(ctx, vb, d_frame, &d_frame->paddr); - } - - return ret; -} - -static void fimc_dma_run(void *priv) -{ - struct fimc_ctx *ctx = priv; - struct fimc_dev *fimc; - unsigned long flags; - u32 ret; - - if (WARN(!ctx, "null hardware context\n")) - return; - - fimc = ctx->fimc_dev; - spin_lock_irqsave(&fimc->slock, flags); - set_bit(ST_M2M_PEND, &fimc->state); - - spin_lock(&ctx->slock); - ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR); - ret = fimc_prepare_config(ctx, ctx->state); - if (ret) - goto dma_unlock; - - /* Reconfigure hardware if the context has changed. */ - if (fimc->m2m.ctx != ctx) { - ctx->state |= FIMC_PARAMS; - fimc->m2m.ctx = ctx; - } - fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr); - - if (ctx->state & FIMC_PARAMS) { - fimc_hw_set_input_path(ctx); - fimc_hw_set_in_dma(ctx); - ret = fimc_set_scaler_info(ctx); - if (ret) { - spin_unlock(&fimc->slock); - goto dma_unlock; - } - fimc_hw_set_prescaler(ctx); - fimc_hw_set_mainscaler(ctx); - fimc_hw_set_target_format(ctx); - fimc_hw_set_rotation(ctx); - fimc_hw_set_effect(ctx, false); - } - - fimc_hw_set_output_path(ctx); - if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS)) - fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr, -1); - - if (ctx->state & FIMC_PARAMS) { - fimc_hw_set_out_dma(ctx); - if (fimc->variant->has_alpha) - fimc_hw_set_rgb_alpha(ctx); - } - - fimc_activate_capture(ctx); - - ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP | - FIMC_SRC_FMT | FIMC_DST_FMT); - fimc_hw_activate_input_dma(fimc, true); -dma_unlock: - spin_unlock(&ctx->slock); - spin_unlock_irqrestore(&fimc->slock, flags); -} - -static void fimc_job_abort(void *priv) -{ - fimc_m2m_shutdown(priv); -} - -static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, - unsigned int *num_buffers, unsigned int *num_planes, - unsigned int sizes[], void *allocators[]) -{ - struct fimc_ctx *ctx = vb2_get_drv_priv(vq); - struct fimc_frame *f; - int i; - - f = ctx_get_frame(ctx, vq->type); - if (IS_ERR(f)) - return PTR_ERR(f); - /* - * Return number of non-contigous planes (plane buffers) - * depending on the configured color format. - */ - if (!f->fmt) - return -EINVAL; - - *num_planes = f->fmt->memplanes; - for (i = 0; i < f->fmt->memplanes; i++) { - sizes[i] = (f->f_width * f->f_height * f->fmt->depth[i]) / 8; - allocators[i] = ctx->fimc_dev->alloc_ctx; - } - return 0; -} - -static int fimc_buf_prepare(struct vb2_buffer *vb) -{ - struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - struct fimc_frame *frame; - int i; - - frame = ctx_get_frame(ctx, vb->vb2_queue->type); - if (IS_ERR(frame)) - return PTR_ERR(frame); - - for (i = 0; i < frame->fmt->memplanes; i++) - vb2_set_plane_payload(vb, i, frame->payload[i]); - - return 0; -} - -static void fimc_buf_queue(struct vb2_buffer *vb) -{ - struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - - dbg("ctx: %p, ctx->state: 0x%x", ctx, ctx->state); - - if (ctx->m2m_ctx) - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); -} - -static void fimc_lock(struct vb2_queue *vq) -{ - struct fimc_ctx *ctx = vb2_get_drv_priv(vq); - mutex_lock(&ctx->fimc_dev->lock); -} - -static void fimc_unlock(struct vb2_queue *vq) -{ - struct fimc_ctx *ctx = vb2_get_drv_priv(vq); - mutex_unlock(&ctx->fimc_dev->lock); -} - -static struct vb2_ops fimc_qops = { - .queue_setup = fimc_queue_setup, - .buf_prepare = fimc_buf_prepare, - .buf_queue = fimc_buf_queue, - .wait_prepare = fimc_unlock, - .wait_finish = fimc_lock, - .stop_streaming = stop_streaming, - .start_streaming = start_streaming, -}; - -/* - * V4L2 controls handling - */ -#define ctrl_to_ctx(__ctrl) \ - container_of((__ctrl)->handler, struct fimc_ctx, ctrl_handler) - -static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - struct samsung_fimc_variant *variant = fimc->variant; - unsigned int flags = FIMC_DST_FMT | FIMC_SRC_FMT; - int ret = 0; - - if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) - return 0; - - switch (ctrl->id) { - case V4L2_CID_HFLIP: - ctx->hflip = ctrl->val; - break; - - case V4L2_CID_VFLIP: - ctx->vflip = ctrl->val; - break; - - case V4L2_CID_ROTATE: - if (fimc_capture_pending(fimc) || - (ctx->state & flags) == flags) { - ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, - ctx->s_frame.height, ctx->d_frame.width, - ctx->d_frame.height, ctrl->val); - if (ret) - return -EINVAL; - } - if ((ctrl->val == 90 || ctrl->val == 270) && - !variant->has_out_rot) - return -EINVAL; - - ctx->rotation = ctrl->val; - break; - - case V4L2_CID_ALPHA_COMPONENT: - ctx->d_frame.alpha = ctrl->val; - break; - } - ctx->state |= FIMC_PARAMS; - set_bit(ST_CAPT_APPLY_CFG, &fimc->state); - return 0; -} - -static int fimc_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct fimc_ctx *ctx = ctrl_to_ctx(ctrl); - unsigned long flags; - int ret; - - spin_lock_irqsave(&ctx->slock, flags); - ret = __fimc_s_ctrl(ctx, ctrl); - spin_unlock_irqrestore(&ctx->slock, flags); - - return ret; -} - -static const struct v4l2_ctrl_ops fimc_ctrl_ops = { - .s_ctrl = fimc_s_ctrl, -}; - -int fimc_ctrls_create(struct fimc_ctx *ctx) -{ - struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; - unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt); - - if (ctx->ctrls_rdy) - return 0; - v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4); - - ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops, - V4L2_CID_ROTATE, 0, 270, 90, 0); - ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - if (variant->has_alpha) - ctx->ctrl_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler, - &fimc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, - 0, max_alpha, 1, 0); - else - ctx->ctrl_alpha = NULL; - - ctx->ctrls_rdy = ctx->ctrl_handler.error == 0; - - return ctx->ctrl_handler.error; -} - -void fimc_ctrls_delete(struct fimc_ctx *ctx) -{ - if (ctx->ctrls_rdy) { - v4l2_ctrl_handler_free(&ctx->ctrl_handler); - ctx->ctrls_rdy = false; - ctx->ctrl_alpha = NULL; - } -} - -void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active) -{ - unsigned int has_alpha = ctx->d_frame.fmt->flags & FMT_HAS_ALPHA; - - if (!ctx->ctrls_rdy) - return; - - mutex_lock(&ctx->ctrl_handler.lock); - v4l2_ctrl_activate(ctx->ctrl_rotate, active); - v4l2_ctrl_activate(ctx->ctrl_hflip, active); - v4l2_ctrl_activate(ctx->ctrl_vflip, active); - if (ctx->ctrl_alpha) - v4l2_ctrl_activate(ctx->ctrl_alpha, active && has_alpha); - - if (active) { - ctx->rotation = ctx->ctrl_rotate->val; - ctx->hflip = ctx->ctrl_hflip->val; - ctx->vflip = ctx->ctrl_vflip->val; - } else { - ctx->rotation = 0; - ctx->hflip = 0; - ctx->vflip = 0; - } - mutex_unlock(&ctx->ctrl_handler.lock); -} - -/* Update maximum value of the alpha color control */ -void fimc_alpha_ctrl_update(struct fimc_ctx *ctx) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - struct v4l2_ctrl *ctrl = ctx->ctrl_alpha; - - if (ctrl == NULL || !fimc->variant->has_alpha) - return; - - v4l2_ctrl_lock(ctrl); - ctrl->maximum = fimc_get_alpha_mask(ctx->d_frame.fmt); - - if (ctrl->cur.val > ctrl->maximum) - ctrl->cur.val = ctrl->maximum; - - v4l2_ctrl_unlock(ctrl); -} - -/* - * V4L2 ioctl handlers - */ -static int fimc_m2m_querycap(struct file *file, void *fh, - struct v4l2_capability *cap) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - struct fimc_dev *fimc = ctx->fimc_dev; - - strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1); - strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1); - cap->bus_info[0] = 0; - cap->capabilities = V4L2_CAP_STREAMING | - V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE; - - return 0; -} - -static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct fimc_fmt *fmt; - - fmt = fimc_find_format(NULL, NULL, get_m2m_fmt_flags(f->type), - f->index); - if (!fmt) - return -EINVAL; - - strncpy(f->description, fmt->name, sizeof(f->description) - 1); - f->pixelformat = fmt->fourcc; - return 0; -} - -int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f) -{ - struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; - int i; - - pixm->width = frame->o_width; - pixm->height = frame->o_height; - pixm->field = V4L2_FIELD_NONE; - pixm->pixelformat = frame->fmt->fourcc; - pixm->colorspace = V4L2_COLORSPACE_JPEG; - pixm->num_planes = frame->fmt->memplanes; - - for (i = 0; i < pixm->num_planes; ++i) { - int bpl = frame->f_width; - if (frame->fmt->colplanes == 1) /* packed formats */ - bpl = (bpl * frame->fmt->depth[0]) / 8; - pixm->plane_fmt[i].bytesperline = bpl; - pixm->plane_fmt[i].sizeimage = (frame->o_width * - frame->o_height * frame->fmt->depth[i]) / 8; - } - return 0; -} - -void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f) -{ - struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; - - frame->f_width = pixm->plane_fmt[0].bytesperline; - if (frame->fmt->colplanes == 1) - frame->f_width = (frame->f_width * 8) / frame->fmt->depth[0]; - frame->f_height = pixm->height; - frame->width = pixm->width; - frame->height = pixm->height; - frame->o_width = pixm->width; - frame->o_height = pixm->height; - frame->offs_h = 0; - frame->offs_v = 0; -} - -/** - * fimc_adjust_mplane_format - adjust bytesperline/sizeimage for each plane - * @fmt: fimc pixel format description (input) - * @width: requested pixel width - * @height: requested pixel height - * @pix: multi-plane format to adjust - */ -void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height, - struct v4l2_pix_format_mplane *pix) -{ - u32 bytesperline = 0; - int i; - - pix->colorspace = V4L2_COLORSPACE_JPEG; - pix->field = V4L2_FIELD_NONE; - pix->num_planes = fmt->memplanes; - pix->pixelformat = fmt->fourcc; - pix->height = height; - pix->width = width; - - for (i = 0; i < pix->num_planes; ++i) { - u32 bpl = pix->plane_fmt[i].bytesperline; - u32 *sizeimage = &pix->plane_fmt[i].sizeimage; - - if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width)) - bpl = pix->width; /* Planar */ - - if (fmt->colplanes == 1 && /* Packed */ - (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width)) - bpl = (pix->width * fmt->depth[0]) / 8; - - if (i == 0) /* Same bytesperline for each plane. */ - bytesperline = bpl; - - pix->plane_fmt[i].bytesperline = bytesperline; - *sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8; - } -} - -static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - struct fimc_frame *frame = ctx_get_frame(ctx, f->type); - - if (IS_ERR(frame)) - return PTR_ERR(frame); - - return fimc_fill_format(frame, f); -} - -/** - * fimc_find_format - lookup fimc color format by fourcc or media bus format - * @pixelformat: fourcc to match, ignored if null - * @mbus_code: media bus code to match, ignored if null - * @mask: the color flags to match - * @index: offset in the fimc_formats array, ignored if negative - */ -struct fimc_fmt *fimc_find_format(const u32 *pixelformat, const u32 *mbus_code, - unsigned int mask, int index) -{ - struct fimc_fmt *fmt, *def_fmt = NULL; - unsigned int i; - int id = 0; - - if (index >= (int)ARRAY_SIZE(fimc_formats)) - return NULL; - - for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) { - fmt = &fimc_formats[i]; - if (!(fmt->flags & mask)) - continue; - if (pixelformat && fmt->fourcc == *pixelformat) - return fmt; - if (mbus_code && fmt->mbus_code == *mbus_code) - return fmt; - if (index == id) - def_fmt = fmt; - id++; - } - return def_fmt; -} - -static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - struct samsung_fimc_variant *variant = fimc->variant; - struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct fimc_fmt *fmt; - u32 max_w, mod_x, mod_y; - - if (!IS_M2M(f->type)) - return -EINVAL; - - dbg("w: %d, h: %d", pix->width, pix->height); - - fmt = fimc_find_format(&pix->pixelformat, NULL, - get_m2m_fmt_flags(f->type), 0); - if (WARN(fmt == NULL, "Pixel format lookup failed")) - return -EINVAL; - - if (pix->field == V4L2_FIELD_ANY) - pix->field = V4L2_FIELD_NONE; - else if (pix->field != V4L2_FIELD_NONE) - return -EINVAL; - - if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - max_w = variant->pix_limit->scaler_dis_w; - mod_x = ffs(variant->min_inp_pixsize) - 1; - } else { - max_w = variant->pix_limit->out_rot_dis_w; - mod_x = ffs(variant->min_out_pixsize) - 1; - } - - if (tiled_fmt(fmt)) { - mod_x = 6; /* 64 x 32 pixels tile */ - mod_y = 5; - } else { - if (variant->min_vsize_align == 1) - mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1; - else - mod_y = ffs(variant->min_vsize_align) - 1; - } - - v4l_bound_align_image(&pix->width, 16, max_w, mod_x, - &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0); - - fimc_adjust_mplane_format(fmt, pix->width, pix->height, &f->fmt.pix_mp); - return 0; -} - -static int fimc_m2m_try_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - - return fimc_try_fmt_mplane(ctx, f); -} - -static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - struct fimc_dev *fimc = ctx->fimc_dev; - struct vb2_queue *vq; - struct fimc_frame *frame; - struct v4l2_pix_format_mplane *pix; - int i, ret = 0; - - ret = fimc_try_fmt_mplane(ctx, f); - if (ret) - return ret; - - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); - - if (vb2_is_busy(vq)) { - v4l2_err(fimc->m2m.vfd, "queue (%d) busy\n", f->type); - return -EBUSY; - } - - if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - frame = &ctx->s_frame; - else - frame = &ctx->d_frame; - - pix = &f->fmt.pix_mp; - frame->fmt = fimc_find_format(&pix->pixelformat, NULL, - get_m2m_fmt_flags(f->type), 0); - if (!frame->fmt) - return -EINVAL; - - /* Update RGB Alpha control state and value range */ - fimc_alpha_ctrl_update(ctx); - - for (i = 0; i < frame->fmt->colplanes; i++) { - frame->payload[i] = - (pix->width * pix->height * frame->fmt->depth[i]) / 8; - } - - fimc_fill_frame(frame, f); - - ctx->scaler.enabled = 1; - - if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_DST_FMT, ctx); - else - fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_SRC_FMT, ctx); - - dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height); - - return 0; -} - -static int fimc_m2m_reqbufs(struct file *file, void *fh, - struct v4l2_requestbuffers *reqbufs) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); -} - -static int fimc_m2m_querybuf(struct file *file, void *fh, - struct v4l2_buffer *buf) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - - return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); -} - -static int fimc_m2m_qbuf(struct file *file, void *fh, - struct v4l2_buffer *buf) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); -} - -static int fimc_m2m_dqbuf(struct file *file, void *fh, - struct v4l2_buffer *buf) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); -} - -static int fimc_m2m_streamon(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - - /* The source and target color format need to be set */ - if (V4L2_TYPE_IS_OUTPUT(type)) { - if (!fimc_ctx_state_is_set(FIMC_SRC_FMT, ctx)) - return -EINVAL; - } else if (!fimc_ctx_state_is_set(FIMC_DST_FMT, ctx)) { - return -EINVAL; - } - - return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); -} - -static int fimc_m2m_streamoff(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - - return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); -} - -static int fimc_m2m_cropcap(struct file *file, void *fh, - struct v4l2_cropcap *cr) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - struct fimc_frame *frame; - - frame = ctx_get_frame(ctx, cr->type); - if (IS_ERR(frame)) - return PTR_ERR(frame); - - cr->bounds.left = 0; - cr->bounds.top = 0; - cr->bounds.width = frame->o_width; - cr->bounds.height = frame->o_height; - cr->defrect = cr->bounds; - - return 0; -} - -static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - struct fimc_frame *frame; - - frame = ctx_get_frame(ctx, cr->type); - if (IS_ERR(frame)) - return PTR_ERR(frame); - - cr->c.left = frame->offs_h; - cr->c.top = frame->offs_v; - cr->c.width = frame->width; - cr->c.height = frame->height; - - return 0; -} - -static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - struct fimc_frame *f; - u32 min_size, halign, depth = 0; - int i; - - if (cr->c.top < 0 || cr->c.left < 0) { - v4l2_err(fimc->m2m.vfd, - "doesn't support negative values for top & left\n"); - return -EINVAL; - } - if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - f = &ctx->d_frame; - else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - f = &ctx->s_frame; - else - return -EINVAL; - - min_size = (f == &ctx->s_frame) ? - fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize; - - /* Get pixel alignment constraints. */ - if (fimc->variant->min_vsize_align == 1) - halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1; - else - halign = ffs(fimc->variant->min_vsize_align) - 1; - - for (i = 0; i < f->fmt->colplanes; i++) - depth += f->fmt->depth[i]; - - v4l_bound_align_image(&cr->c.width, min_size, f->o_width, - ffs(min_size) - 1, - &cr->c.height, min_size, f->o_height, - halign, 64/(ALIGN(depth, 8))); - - /* adjust left/top if cropping rectangle is out of bounds */ - if (cr->c.left + cr->c.width > f->o_width) - cr->c.left = f->o_width - cr->c.width; - if (cr->c.top + cr->c.height > f->o_height) - cr->c.top = f->o_height - cr->c.height; - - cr->c.left = round_down(cr->c.left, min_size); - cr->c.top = round_down(cr->c.top, fimc->variant->hor_offs_align); - - dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d", - cr->c.left, cr->c.top, cr->c.width, cr->c.height, - f->f_width, f->f_height); - - return 0; -} - -static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - struct fimc_dev *fimc = ctx->fimc_dev; - struct fimc_frame *f; - int ret; - - ret = fimc_m2m_try_crop(ctx, cr); - if (ret) - return ret; - - f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? - &ctx->s_frame : &ctx->d_frame; - - /* Check to see if scaling ratio is within supported range */ - if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) { - if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - ret = fimc_check_scaler_ratio(ctx, cr->c.width, - cr->c.height, ctx->d_frame.width, - ctx->d_frame.height, ctx->rotation); - } else { - ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, - ctx->s_frame.height, cr->c.width, - cr->c.height, ctx->rotation); - } - if (ret) { - v4l2_err(fimc->m2m.vfd, "Out of scaler range\n"); - return -EINVAL; - } - } - - f->offs_h = cr->c.left; - f->offs_v = cr->c.top; - f->width = cr->c.width; - f->height = cr->c.height; - - fimc_ctx_state_lock_set(FIMC_PARAMS, ctx); - - return 0; -} - -static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = { - .vidioc_querycap = fimc_m2m_querycap, - - .vidioc_enum_fmt_vid_cap_mplane = fimc_m2m_enum_fmt_mplane, - .vidioc_enum_fmt_vid_out_mplane = fimc_m2m_enum_fmt_mplane, - - .vidioc_g_fmt_vid_cap_mplane = fimc_m2m_g_fmt_mplane, - .vidioc_g_fmt_vid_out_mplane = fimc_m2m_g_fmt_mplane, - - .vidioc_try_fmt_vid_cap_mplane = fimc_m2m_try_fmt_mplane, - .vidioc_try_fmt_vid_out_mplane = fimc_m2m_try_fmt_mplane, - - .vidioc_s_fmt_vid_cap_mplane = fimc_m2m_s_fmt_mplane, - .vidioc_s_fmt_vid_out_mplane = fimc_m2m_s_fmt_mplane, - - .vidioc_reqbufs = fimc_m2m_reqbufs, - .vidioc_querybuf = fimc_m2m_querybuf, - - .vidioc_qbuf = fimc_m2m_qbuf, - .vidioc_dqbuf = fimc_m2m_dqbuf, - - .vidioc_streamon = fimc_m2m_streamon, - .vidioc_streamoff = fimc_m2m_streamoff, - - .vidioc_g_crop = fimc_m2m_g_crop, - .vidioc_s_crop = fimc_m2m_s_crop, - .vidioc_cropcap = fimc_m2m_cropcap - -}; - -static int queue_init(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq) -{ - struct fimc_ctx *ctx = priv; - int ret; - - memset(src_vq, 0, sizeof(*src_vq)); - src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - src_vq->io_modes = VB2_MMAP | VB2_USERPTR; - src_vq->drv_priv = ctx; - src_vq->ops = &fimc_qops; - src_vq->mem_ops = &vb2_dma_contig_memops; - src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); - - ret = vb2_queue_init(src_vq); - if (ret) - return ret; - - memset(dst_vq, 0, sizeof(*dst_vq)); - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; - dst_vq->drv_priv = ctx; - dst_vq->ops = &fimc_qops; - dst_vq->mem_ops = &vb2_dma_contig_memops; - dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); - - return vb2_queue_init(dst_vq); -} - -static int fimc_m2m_open(struct file *file) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_ctx *ctx; - int ret; - - dbg("pid: %d, state: 0x%lx, refcnt: %d", - task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt); - - /* - * Return if the corresponding video capture node - * is already opened. - */ - if (fimc->vid_cap.refcnt > 0) - return -EBUSY; - - ctx = kzalloc(sizeof *ctx, GFP_KERNEL); - if (!ctx) - return -ENOMEM; - v4l2_fh_init(&ctx->fh, fimc->m2m.vfd); - ctx->fimc_dev = fimc; - - /* Default color format */ - ctx->s_frame.fmt = &fimc_formats[0]; - ctx->d_frame.fmt = &fimc_formats[0]; - - ret = fimc_ctrls_create(ctx); - if (ret) - goto error_fh; - - /* Use separate control handler per file handle */ - ctx->fh.ctrl_handler = &ctx->ctrl_handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); - - /* Setup the device context for memory-to-memory mode */ - ctx->state = FIMC_CTX_M2M; - ctx->flags = 0; - ctx->in_path = FIMC_DMA; - ctx->out_path = FIMC_DMA; - spin_lock_init(&ctx->slock); - - ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); - if (IS_ERR(ctx->m2m_ctx)) { - ret = PTR_ERR(ctx->m2m_ctx); - goto error_c; - } - - if (fimc->m2m.refcnt++ == 0) - set_bit(ST_M2M_RUN, &fimc->state); - return 0; - -error_c: - fimc_ctrls_delete(ctx); -error_fh: - v4l2_fh_del(&ctx->fh); - v4l2_fh_exit(&ctx->fh); - kfree(ctx); - return ret; -} - -static int fimc_m2m_release(struct file *file) -{ - struct fimc_ctx *ctx = fh_to_ctx(file->private_data); - struct fimc_dev *fimc = ctx->fimc_dev; - - dbg("pid: %d, state: 0x%lx, refcnt= %d", - task_pid_nr(current), fimc->state, fimc->m2m.refcnt); - - v4l2_m2m_ctx_release(ctx->m2m_ctx); - fimc_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); - v4l2_fh_exit(&ctx->fh); - - if (--fimc->m2m.refcnt <= 0) - clear_bit(ST_M2M_RUN, &fimc->state); - kfree(ctx); - return 0; -} - -static unsigned int fimc_m2m_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct fimc_ctx *ctx = fh_to_ctx(file->private_data); - - return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); -} - - -static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct fimc_ctx *ctx = fh_to_ctx(file->private_data); - - return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); -} - -static const struct v4l2_file_operations fimc_m2m_fops = { - .owner = THIS_MODULE, - .open = fimc_m2m_open, - .release = fimc_m2m_release, - .poll = fimc_m2m_poll, - .unlocked_ioctl = video_ioctl2, - .mmap = fimc_m2m_mmap, -}; - -static struct v4l2_m2m_ops m2m_ops = { - .device_run = fimc_dma_run, - .job_abort = fimc_job_abort, -}; - -int fimc_register_m2m_device(struct fimc_dev *fimc, - struct v4l2_device *v4l2_dev) -{ - struct video_device *vfd; - struct platform_device *pdev; - int ret = 0; - - if (!fimc) - return -ENODEV; - - pdev = fimc->pdev; - fimc->v4l2_dev = v4l2_dev; - - vfd = video_device_alloc(); - if (!vfd) { - v4l2_err(v4l2_dev, "Failed to allocate video device\n"); - return -ENOMEM; - } - - vfd->fops = &fimc_m2m_fops; - vfd->ioctl_ops = &fimc_m2m_ioctl_ops; - vfd->v4l2_dev = v4l2_dev; - vfd->minor = -1; - vfd->release = video_device_release; - vfd->lock = &fimc->lock; - - snprintf(vfd->name, sizeof(vfd->name), "%s.m2m", dev_name(&pdev->dev)); - video_set_drvdata(vfd, fimc); - - fimc->m2m.vfd = vfd; - fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops); - if (IS_ERR(fimc->m2m.m2m_dev)) { - v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n"); - ret = PTR_ERR(fimc->m2m.m2m_dev); - goto err_init; - } - - ret = media_entity_init(&vfd->entity, 0, NULL, 0); - if (!ret) - return 0; - - v4l2_m2m_release(fimc->m2m.m2m_dev); -err_init: - video_device_release(fimc->m2m.vfd); - return ret; -} - -void fimc_unregister_m2m_device(struct fimc_dev *fimc) -{ - if (!fimc) - return; - - if (fimc->m2m.m2m_dev) - v4l2_m2m_release(fimc->m2m.m2m_dev); - if (fimc->m2m.vfd) { - media_entity_cleanup(&fimc->m2m.vfd->entity); - /* Can also be called if video device wasn't registered */ - video_unregister_device(fimc->m2m.vfd); - } -} - -static void fimc_clk_put(struct fimc_dev *fimc) -{ - int i; - for (i = 0; i < fimc->num_clocks; i++) { - if (IS_ERR_OR_NULL(fimc->clock[i])) - continue; - clk_unprepare(fimc->clock[i]); - clk_put(fimc->clock[i]); - fimc->clock[i] = NULL; - } -} - -static int fimc_clk_get(struct fimc_dev *fimc) -{ - int i, ret; - - for (i = 0; i < fimc->num_clocks; i++) { - fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); - if (IS_ERR(fimc->clock[i])) - goto err; - ret = clk_prepare(fimc->clock[i]); - if (ret < 0) { - clk_put(fimc->clock[i]); - fimc->clock[i] = NULL; - goto err; - } - } - return 0; -err: - fimc_clk_put(fimc); - dev_err(&fimc->pdev->dev, "failed to get clock: %s\n", - fimc_clocks[i]); - return -ENXIO; -} - -static int fimc_m2m_suspend(struct fimc_dev *fimc) -{ - unsigned long flags; - int timeout; - - spin_lock_irqsave(&fimc->slock, flags); - if (!fimc_m2m_pending(fimc)) { - spin_unlock_irqrestore(&fimc->slock, flags); - return 0; - } - clear_bit(ST_M2M_SUSPENDED, &fimc->state); - set_bit(ST_M2M_SUSPENDING, &fimc->state); - spin_unlock_irqrestore(&fimc->slock, flags); - - timeout = wait_event_timeout(fimc->irq_queue, - test_bit(ST_M2M_SUSPENDED, &fimc->state), - FIMC_SHUTDOWN_TIMEOUT); - - clear_bit(ST_M2M_SUSPENDING, &fimc->state); - return timeout == 0 ? -EAGAIN : 0; -} - -static int fimc_m2m_resume(struct fimc_dev *fimc) -{ - unsigned long flags; - - spin_lock_irqsave(&fimc->slock, flags); - /* Clear for full H/W setup in first run after resume */ - fimc->m2m.ctx = NULL; - spin_unlock_irqrestore(&fimc->slock, flags); - - if (test_and_clear_bit(ST_M2M_SUSPENDED, &fimc->state)) - fimc_m2m_job_finish(fimc->m2m.ctx, - VB2_BUF_STATE_ERROR); - return 0; -} - -static int fimc_probe(struct platform_device *pdev) -{ - struct fimc_dev *fimc; - struct resource *res; - struct samsung_fimc_driverdata *drv_data; - struct s5p_platform_fimc *pdata; - int ret = 0; - - drv_data = (struct samsung_fimc_driverdata *) - platform_get_device_id(pdev)->driver_data; - - if (pdev->id >= drv_data->num_entities) { - dev_err(&pdev->dev, "Invalid platform device id: %d\n", - pdev->id); - return -EINVAL; - } - - fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL); - if (!fimc) - return -ENOMEM; - - fimc->id = pdev->id; - - fimc->variant = drv_data->variant[fimc->id]; - fimc->pdev = pdev; - pdata = pdev->dev.platform_data; - fimc->pdata = pdata; - - init_waitqueue_head(&fimc->irq_queue); - spin_lock_init(&fimc->slock); - mutex_init(&fimc->lock); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - fimc->regs = devm_request_and_ioremap(&pdev->dev, res); - if (fimc->regs == NULL) { - dev_err(&pdev->dev, "Failed to obtain io memory\n"); - return -ENOENT; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res == NULL) { - dev_err(&pdev->dev, "Failed to get IRQ resource\n"); - return -ENXIO; - } - fimc->irq = res->start; - - fimc->num_clocks = MAX_FIMC_CLOCKS; - ret = fimc_clk_get(fimc); - if (ret) - return ret; - clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); - clk_enable(fimc->clock[CLK_BUS]); - - platform_set_drvdata(pdev, fimc); - - ret = devm_request_irq(&pdev->dev, fimc->irq, fimc_irq_handler, - 0, pdev->name, fimc); - if (ret) { - dev_err(&pdev->dev, "failed to install irq (%d)\n", ret); - goto err_clk; - } - - pm_runtime_enable(&pdev->dev); - ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) - goto err_clk; - /* Initialize contiguous memory allocator */ - fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); - if (IS_ERR(fimc->alloc_ctx)) { - ret = PTR_ERR(fimc->alloc_ctx); - goto err_pm; - } - - dev_dbg(&pdev->dev, "FIMC.%d registered successfully\n", fimc->id); - - pm_runtime_put(&pdev->dev); - return 0; - -err_pm: - pm_runtime_put(&pdev->dev); -err_clk: - fimc_clk_put(fimc); - return ret; -} - -static int fimc_runtime_resume(struct device *dev) -{ - struct fimc_dev *fimc = dev_get_drvdata(dev); - - dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state); - - /* Enable clocks and perform basic initalization */ - clk_enable(fimc->clock[CLK_GATE]); - fimc_hw_reset(fimc); - - /* Resume the capture or mem-to-mem device */ - if (fimc_capture_busy(fimc)) - return fimc_capture_resume(fimc); - - return fimc_m2m_resume(fimc); -} - -static int fimc_runtime_suspend(struct device *dev) -{ - struct fimc_dev *fimc = dev_get_drvdata(dev); - int ret = 0; - - if (fimc_capture_busy(fimc)) - ret = fimc_capture_suspend(fimc); - else - ret = fimc_m2m_suspend(fimc); - if (!ret) - clk_disable(fimc->clock[CLK_GATE]); - - dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state); - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static int fimc_resume(struct device *dev) -{ - struct fimc_dev *fimc = dev_get_drvdata(dev); - unsigned long flags; - - dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state); - - /* Do not resume if the device was idle before system suspend */ - spin_lock_irqsave(&fimc->slock, flags); - if (!test_and_clear_bit(ST_LPM, &fimc->state) || - (!fimc_m2m_active(fimc) && !fimc_capture_busy(fimc))) { - spin_unlock_irqrestore(&fimc->slock, flags); - return 0; - } - fimc_hw_reset(fimc); - spin_unlock_irqrestore(&fimc->slock, flags); - - if (fimc_capture_busy(fimc)) - return fimc_capture_resume(fimc); - - return fimc_m2m_resume(fimc); -} - -static int fimc_suspend(struct device *dev) -{ - struct fimc_dev *fimc = dev_get_drvdata(dev); - - dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state); - - if (test_and_set_bit(ST_LPM, &fimc->state)) - return 0; - if (fimc_capture_busy(fimc)) - return fimc_capture_suspend(fimc); - - return fimc_m2m_suspend(fimc); -} -#endif /* CONFIG_PM_SLEEP */ - -static int __devexit fimc_remove(struct platform_device *pdev) -{ - struct fimc_dev *fimc = platform_get_drvdata(pdev); - - pm_runtime_disable(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); - - vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx); - - clk_disable(fimc->clock[CLK_BUS]); - fimc_clk_put(fimc); - - dev_info(&pdev->dev, "driver unloaded\n"); - return 0; -} - -/* Image pixel limits, similar across several FIMC HW revisions. */ -static struct fimc_pix_limit s5p_pix_limit[4] = { - [0] = { - .scaler_en_w = 3264, - .scaler_dis_w = 8192, - .in_rot_en_h = 1920, - .in_rot_dis_w = 8192, - .out_rot_en_w = 1920, - .out_rot_dis_w = 4224, - }, - [1] = { - .scaler_en_w = 4224, - .scaler_dis_w = 8192, - .in_rot_en_h = 1920, - .in_rot_dis_w = 8192, - .out_rot_en_w = 1920, - .out_rot_dis_w = 4224, - }, - [2] = { - .scaler_en_w = 1920, - .scaler_dis_w = 8192, - .in_rot_en_h = 1280, - .in_rot_dis_w = 8192, - .out_rot_en_w = 1280, - .out_rot_dis_w = 1920, - }, - [3] = { - .scaler_en_w = 1920, - .scaler_dis_w = 8192, - .in_rot_en_h = 1366, - .in_rot_dis_w = 8192, - .out_rot_en_w = 1366, - .out_rot_dis_w = 1920, - }, -}; - -static struct samsung_fimc_variant fimc0_variant_s5p = { - .has_inp_rot = 1, - .has_out_rot = 1, - .has_cam_if = 1, - .min_inp_pixsize = 16, - .min_out_pixsize = 16, - .hor_offs_align = 8, - .min_vsize_align = 16, - .out_buf_count = 4, - .pix_limit = &s5p_pix_limit[0], -}; - -static struct samsung_fimc_variant fimc2_variant_s5p = { - .has_cam_if = 1, - .min_inp_pixsize = 16, - .min_out_pixsize = 16, - .hor_offs_align = 8, - .min_vsize_align = 16, - .out_buf_count = 4, - .pix_limit = &s5p_pix_limit[1], -}; - -static struct samsung_fimc_variant fimc0_variant_s5pv210 = { - .pix_hoff = 1, - .has_inp_rot = 1, - .has_out_rot = 1, - .has_cam_if = 1, - .min_inp_pixsize = 16, - .min_out_pixsize = 16, - .hor_offs_align = 8, - .min_vsize_align = 16, - .out_buf_count = 4, - .pix_limit = &s5p_pix_limit[1], -}; - -static struct samsung_fimc_variant fimc1_variant_s5pv210 = { - .pix_hoff = 1, - .has_inp_rot = 1, - .has_out_rot = 1, - .has_cam_if = 1, - .has_mainscaler_ext = 1, - .min_inp_pixsize = 16, - .min_out_pixsize = 16, - .hor_offs_align = 1, - .min_vsize_align = 1, - .out_buf_count = 4, - .pix_limit = &s5p_pix_limit[2], -}; - -static struct samsung_fimc_variant fimc2_variant_s5pv210 = { - .has_cam_if = 1, - .pix_hoff = 1, - .min_inp_pixsize = 16, - .min_out_pixsize = 16, - .hor_offs_align = 8, - .min_vsize_align = 16, - .out_buf_count = 4, - .pix_limit = &s5p_pix_limit[2], -}; - -static struct samsung_fimc_variant fimc0_variant_exynos4 = { - .pix_hoff = 1, - .has_inp_rot = 1, - .has_out_rot = 1, - .has_cam_if = 1, - .has_cistatus2 = 1, - .has_mainscaler_ext = 1, - .has_alpha = 1, - .min_inp_pixsize = 16, - .min_out_pixsize = 16, - .hor_offs_align = 2, - .min_vsize_align = 1, - .out_buf_count = 32, - .pix_limit = &s5p_pix_limit[1], -}; - -static struct samsung_fimc_variant fimc3_variant_exynos4 = { - .pix_hoff = 1, - .has_cam_if = 1, - .has_cistatus2 = 1, - .has_mainscaler_ext = 1, - .has_alpha = 1, - .min_inp_pixsize = 16, - .min_out_pixsize = 16, - .hor_offs_align = 2, - .min_vsize_align = 1, - .out_buf_count = 32, - .pix_limit = &s5p_pix_limit[3], -}; - -/* S5PC100 */ -static struct samsung_fimc_driverdata fimc_drvdata_s5p = { - .variant = { - [0] = &fimc0_variant_s5p, - [1] = &fimc0_variant_s5p, - [2] = &fimc2_variant_s5p, - }, - .num_entities = 3, - .lclk_frequency = 133000000UL, -}; - -/* S5PV210, S5PC110 */ -static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = { - .variant = { - [0] = &fimc0_variant_s5pv210, - [1] = &fimc1_variant_s5pv210, - [2] = &fimc2_variant_s5pv210, - }, - .num_entities = 3, - .lclk_frequency = 166000000UL, -}; - -/* S5PV310, S5PC210 */ -static struct samsung_fimc_driverdata fimc_drvdata_exynos4 = { - .variant = { - [0] = &fimc0_variant_exynos4, - [1] = &fimc0_variant_exynos4, - [2] = &fimc0_variant_exynos4, - [3] = &fimc3_variant_exynos4, - }, - .num_entities = 4, - .lclk_frequency = 166000000UL, -}; - -static struct platform_device_id fimc_driver_ids[] = { - { - .name = "s5p-fimc", - .driver_data = (unsigned long)&fimc_drvdata_s5p, - }, { - .name = "s5pv210-fimc", - .driver_data = (unsigned long)&fimc_drvdata_s5pv210, - }, { - .name = "exynos4-fimc", - .driver_data = (unsigned long)&fimc_drvdata_exynos4, - }, - {}, -}; -MODULE_DEVICE_TABLE(platform, fimc_driver_ids); - -static const struct dev_pm_ops fimc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume) - SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL) -}; - -static struct platform_driver fimc_driver = { - .probe = fimc_probe, - .remove = __devexit_p(fimc_remove), - .id_table = fimc_driver_ids, - .driver = { - .name = FIMC_MODULE_NAME, - .owner = THIS_MODULE, - .pm = &fimc_pm_ops, - } -}; - -int __init fimc_register_driver(void) -{ - return platform_driver_probe(&fimc_driver, fimc_probe); -} - -void __exit fimc_unregister_driver(void) -{ - platform_driver_unregister(&fimc_driver); -} diff --git a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-core.h b/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-core.h deleted file mode 100644 index 84fd8355..00000000 --- a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-core.h +++ /dev/null @@ -1,826 +0,0 @@ -/* - * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef FIMC_CORE_H_ -#define FIMC_CORE_H_ - -/*#define DEBUG*/ - -#include <linux/platform_device.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/types.h> -#include <linux/videodev2.h> -#include <linux/io.h> - -#include <media/media-entity.h> -#include <media/videobuf2-core.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> -#include <media/v4l2-mem2mem.h> -#include <media/v4l2-mediabus.h> -#include <media/s5p_fimc.h> - -#include "regs-fimc.h" - -#define err(fmt, args...) \ - printk(KERN_ERR "%s:%d: " fmt "\n", __func__, __LINE__, ##args) - -#define dbg(fmt, args...) \ - pr_debug("%s:%d: " fmt "\n", __func__, __LINE__, ##args) - -/* Time to wait for next frame VSYNC interrupt while stopping operation. */ -#define FIMC_SHUTDOWN_TIMEOUT ((100*HZ)/1000) -#define MAX_FIMC_CLOCKS 2 -#define FIMC_MODULE_NAME "s5p-fimc" -#define FIMC_MAX_DEVS 4 -#define FIMC_MAX_OUT_BUFS 4 -#define SCALER_MAX_HRATIO 64 -#define SCALER_MAX_VRATIO 64 -#define DMA_MIN_SIZE 8 -#define FIMC_CAMIF_MAX_HEIGHT 0x2000 - -/* indices to the clocks array */ -enum { - CLK_BUS, - CLK_GATE, -}; - -enum fimc_dev_flags { - ST_LPM, - /* m2m node */ - ST_M2M_RUN, - ST_M2M_PEND, - ST_M2M_SUSPENDING, - ST_M2M_SUSPENDED, - /* capture node */ - ST_CAPT_PEND, - ST_CAPT_RUN, - ST_CAPT_STREAM, - ST_CAPT_ISP_STREAM, - ST_CAPT_SUSPENDED, - ST_CAPT_SHUT, - ST_CAPT_BUSY, - ST_CAPT_APPLY_CFG, - ST_CAPT_JPEG, -}; - -#define fimc_m2m_active(dev) test_bit(ST_M2M_RUN, &(dev)->state) -#define fimc_m2m_pending(dev) test_bit(ST_M2M_PEND, &(dev)->state) - -#define fimc_capture_running(dev) test_bit(ST_CAPT_RUN, &(dev)->state) -#define fimc_capture_pending(dev) test_bit(ST_CAPT_PEND, &(dev)->state) -#define fimc_capture_busy(dev) test_bit(ST_CAPT_BUSY, &(dev)->state) - -enum fimc_datapath { - FIMC_CAMERA, - FIMC_DMA, - FIMC_LCDFIFO, - FIMC_WRITEBACK -}; - -enum fimc_color_fmt { - S5P_FIMC_RGB444 = 0x10, - S5P_FIMC_RGB555, - S5P_FIMC_RGB565, - S5P_FIMC_RGB666, - S5P_FIMC_RGB888, - S5P_FIMC_RGB30_LOCAL, - S5P_FIMC_YCBCR420 = 0x20, - S5P_FIMC_YCBYCR422, - S5P_FIMC_YCRYCB422, - S5P_FIMC_CBYCRY422, - S5P_FIMC_CRYCBY422, - S5P_FIMC_YCBCR444_LOCAL, - S5P_FIMC_JPEG = 0x40, -}; - -#define fimc_fmt_is_rgb(x) (!!((x) & 0x10)) -#define fimc_fmt_is_jpeg(x) (!!((x) & 0x40)) - -#define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \ - __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - -/* Cb/Cr chrominance components order for 2 plane Y/CbCr 4:2:2 formats. */ -#define S5P_FIMC_LSB_CRCB S5P_CIOCTRL_ORDER422_2P_LSB_CRCB - -/* The embedded image effect selection */ -#define S5P_FIMC_EFFECT_ORIGINAL S5P_CIIMGEFF_FIN_BYPASS -#define S5P_FIMC_EFFECT_ARBITRARY S5P_CIIMGEFF_FIN_ARBITRARY -#define S5P_FIMC_EFFECT_NEGATIVE S5P_CIIMGEFF_FIN_NEGATIVE -#define S5P_FIMC_EFFECT_ARTFREEZE S5P_CIIMGEFF_FIN_ARTFREEZE -#define S5P_FIMC_EFFECT_EMBOSSING S5P_CIIMGEFF_FIN_EMBOSSING -#define S5P_FIMC_EFFECT_SIKHOUETTE S5P_CIIMGEFF_FIN_SILHOUETTE - -/* The hardware context state. */ -#define FIMC_PARAMS (1 << 0) -#define FIMC_SRC_ADDR (1 << 1) -#define FIMC_DST_ADDR (1 << 2) -#define FIMC_SRC_FMT (1 << 3) -#define FIMC_DST_FMT (1 << 4) -#define FIMC_DST_CROP (1 << 5) -#define FIMC_CTX_M2M (1 << 16) -#define FIMC_CTX_CAP (1 << 17) -#define FIMC_CTX_SHUT (1 << 18) - -/* Image conversion flags */ -#define FIMC_IN_DMA_ACCESS_TILED (1 << 0) -#define FIMC_IN_DMA_ACCESS_LINEAR (0 << 0) -#define FIMC_OUT_DMA_ACCESS_TILED (1 << 1) -#define FIMC_OUT_DMA_ACCESS_LINEAR (0 << 1) -#define FIMC_SCAN_MODE_PROGRESSIVE (0 << 2) -#define FIMC_SCAN_MODE_INTERLACED (1 << 2) -/* - * YCbCr data dynamic range for RGB-YUV color conversion. - * Y/Cb/Cr: (0 ~ 255) */ -#define FIMC_COLOR_RANGE_WIDE (0 << 3) -/* Y (16 ~ 235), Cb/Cr (16 ~ 240) */ -#define FIMC_COLOR_RANGE_NARROW (1 << 3) - -/** - * struct fimc_fmt - the driver's internal color format data - * @mbus_code: Media Bus pixel code, -1 if not applicable - * @name: format description - * @fourcc: the fourcc code for this format, 0 if not applicable - * @color: the corresponding fimc_color_fmt - * @memplanes: number of physically non-contiguous data planes - * @colplanes: number of physically contiguous data planes - * @depth: per plane driver's private 'number of bits per pixel' - * @flags: flags indicating which operation mode format applies to - */ -struct fimc_fmt { - enum v4l2_mbus_pixelcode mbus_code; - char *name; - u32 fourcc; - u32 color; - u16 memplanes; - u16 colplanes; - u8 depth[VIDEO_MAX_PLANES]; - u16 flags; -#define FMT_FLAGS_CAM (1 << 0) -#define FMT_FLAGS_M2M_IN (1 << 1) -#define FMT_FLAGS_M2M_OUT (1 << 2) -#define FMT_FLAGS_M2M (1 << 1 | 1 << 2) -#define FMT_HAS_ALPHA (1 << 3) -}; - -/** - * struct fimc_dma_offset - pixel offset information for DMA - * @y_h: y value horizontal offset - * @y_v: y value vertical offset - * @cb_h: cb value horizontal offset - * @cb_v: cb value vertical offset - * @cr_h: cr value horizontal offset - * @cr_v: cr value vertical offset - */ -struct fimc_dma_offset { - int y_h; - int y_v; - int cb_h; - int cb_v; - int cr_h; - int cr_v; -}; - -/** - * struct fimc_effect - color effect information - * @type: effect type - * @pat_cb: cr value when type is "arbitrary" - * @pat_cr: cr value when type is "arbitrary" - */ -struct fimc_effect { - u32 type; - u8 pat_cb; - u8 pat_cr; -}; - -/** - * struct fimc_scaler - the configuration data for FIMC inetrnal scaler - * @scaleup_h: flag indicating scaling up horizontally - * @scaleup_v: flag indicating scaling up vertically - * @copy_mode: flag indicating transparent DMA transfer (no scaling - * and color format conversion) - * @enabled: flag indicating if the scaler is used - * @hfactor: horizontal shift factor - * @vfactor: vertical shift factor - * @pre_hratio: horizontal ratio of the prescaler - * @pre_vratio: vertical ratio of the prescaler - * @pre_dst_width: the prescaler's destination width - * @pre_dst_height: the prescaler's destination height - * @main_hratio: the main scaler's horizontal ratio - * @main_vratio: the main scaler's vertical ratio - * @real_width: source pixel (width - offset) - * @real_height: source pixel (height - offset) - */ -struct fimc_scaler { - unsigned int scaleup_h:1; - unsigned int scaleup_v:1; - unsigned int copy_mode:1; - unsigned int enabled:1; - u32 hfactor; - u32 vfactor; - u32 pre_hratio; - u32 pre_vratio; - u32 pre_dst_width; - u32 pre_dst_height; - u32 main_hratio; - u32 main_vratio; - u32 real_width; - u32 real_height; -}; - -/** - * struct fimc_addr - the FIMC physical address set for DMA - * @y: luminance plane physical address - * @cb: Cb plane physical address - * @cr: Cr plane physical address - */ -struct fimc_addr { - u32 y; - u32 cb; - u32 cr; -}; - -/** - * struct fimc_vid_buffer - the driver's video buffer - * @vb: v4l videobuf buffer - * @list: linked list structure for buffer queue - * @paddr: precalculated physical address set - * @index: buffer index for the output DMA engine - */ -struct fimc_vid_buffer { - struct vb2_buffer vb; - struct list_head list; - struct fimc_addr paddr; - int index; -}; - -/** - * struct fimc_frame - source/target frame properties - * @f_width: image full width (virtual screen size) - * @f_height: image full height (virtual screen size) - * @o_width: original image width as set by S_FMT - * @o_height: original image height as set by S_FMT - * @offs_h: image horizontal pixel offset - * @offs_v: image vertical pixel offset - * @width: image pixel width - * @height: image pixel weight - * @payload: image size in bytes (w x h x bpp) - * @paddr: image frame buffer physical addresses - * @dma_offset: DMA offset in bytes - * @fmt: fimc color format pointer - */ -struct fimc_frame { - u32 f_width; - u32 f_height; - u32 o_width; - u32 o_height; - u32 offs_h; - u32 offs_v; - u32 width; - u32 height; - unsigned long payload[VIDEO_MAX_PLANES]; - struct fimc_addr paddr; - struct fimc_dma_offset dma_offset; - struct fimc_fmt *fmt; - u8 alpha; -}; - -/** - * struct fimc_m2m_device - v4l2 memory-to-memory device data - * @vfd: the video device node for v4l2 m2m mode - * @m2m_dev: v4l2 memory-to-memory device data - * @ctx: hardware context data - * @refcnt: the reference counter - */ -struct fimc_m2m_device { - struct video_device *vfd; - struct v4l2_m2m_dev *m2m_dev; - struct fimc_ctx *ctx; - int refcnt; -}; - -#define FIMC_SD_PAD_SINK 0 -#define FIMC_SD_PAD_SOURCE 1 -#define FIMC_SD_PADS_NUM 2 - -/** - * struct fimc_vid_cap - camera capture device information - * @ctx: hardware context data - * @vfd: video device node for camera capture mode - * @subdev: subdev exposing the FIMC processing block - * @vd_pad: fimc video capture node pad - * @sd_pads: fimc video processing block pads - * @mf: media bus format at the FIMC camera input (and the scaler output) pad - * @pending_buf_q: the pending buffer queue head - * @active_buf_q: the queue head of buffers scheduled in hardware - * @vbq: the capture am video buffer queue - * @active_buf_cnt: number of video buffers scheduled in hardware - * @buf_index: index for managing the output DMA buffers - * @frame_count: the frame counter for statistics - * @reqbufs_count: the number of buffers requested in REQBUFS ioctl - * @input_index: input (camera sensor) index - * @refcnt: driver's private reference counter - * @input: capture input type, grp_id of the attached subdev - * @user_subdev_api: true if subdevs are not configured by the host driver - */ -struct fimc_vid_cap { - struct fimc_ctx *ctx; - struct vb2_alloc_ctx *alloc_ctx; - struct video_device *vfd; - struct v4l2_subdev *subdev; - struct media_pad vd_pad; - struct v4l2_mbus_framefmt mf; - struct media_pad sd_pads[FIMC_SD_PADS_NUM]; - struct list_head pending_buf_q; - struct list_head active_buf_q; - struct vb2_queue vbq; - int active_buf_cnt; - int buf_index; - unsigned int frame_count; - unsigned int reqbufs_count; - int input_index; - int refcnt; - u32 input; - bool user_subdev_api; -}; - -/** - * struct fimc_pix_limit - image pixel size limits in various IP configurations - * - * @scaler_en_w: max input pixel width when the scaler is enabled - * @scaler_dis_w: max input pixel width when the scaler is disabled - * @in_rot_en_h: max input width with the input rotator is on - * @in_rot_dis_w: max input width with the input rotator is off - * @out_rot_en_w: max output width with the output rotator on - * @out_rot_dis_w: max output width with the output rotator off - */ -struct fimc_pix_limit { - u16 scaler_en_w; - u16 scaler_dis_w; - u16 in_rot_en_h; - u16 in_rot_dis_w; - u16 out_rot_en_w; - u16 out_rot_dis_w; -}; - -/** - * struct samsung_fimc_variant - camera interface variant information - * - * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes - * @has_inp_rot: set if has input rotator - * @has_out_rot: set if has output rotator - * @has_cistatus2: 1 if CISTATUS2 register is present in this IP revision - * @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register - * are present in this IP revision - * @has_cam_if: set if this instance has a camera input interface - * @pix_limit: pixel size constraints for the scaler - * @min_inp_pixsize: minimum input pixel size - * @min_out_pixsize: minimum output pixel size - * @hor_offs_align: horizontal pixel offset aligment - * @min_vsize_align: minimum vertical pixel size alignment - * @out_buf_count: the number of buffers in output DMA sequence - */ -struct samsung_fimc_variant { - unsigned int pix_hoff:1; - unsigned int has_inp_rot:1; - unsigned int has_out_rot:1; - unsigned int has_cistatus2:1; - unsigned int has_mainscaler_ext:1; - unsigned int has_cam_if:1; - unsigned int has_alpha:1; - struct fimc_pix_limit *pix_limit; - u16 min_inp_pixsize; - u16 min_out_pixsize; - u16 hor_offs_align; - u16 min_vsize_align; - u16 out_buf_count; -}; - -/** - * struct samsung_fimc_driverdata - per device type driver data for init time. - * - * @variant: the variant information for this driver. - * @dev_cnt: number of fimc sub-devices available in SoC - * @lclk_frequency: fimc bus clock frequency - */ -struct samsung_fimc_driverdata { - struct samsung_fimc_variant *variant[FIMC_MAX_DEVS]; - unsigned long lclk_frequency; - int num_entities; -}; - -struct fimc_pipeline { - struct media_pipeline *pipe; - struct v4l2_subdev *sensor; - struct v4l2_subdev *csis; -}; - -struct fimc_ctx; - -/** - * struct fimc_dev - abstraction for FIMC entity - * @slock: the spinlock protecting this data structure - * @lock: the mutex protecting this data structure - * @pdev: pointer to the FIMC platform device - * @pdata: pointer to the device platform data - * @variant: the IP variant information - * @id: FIMC device index (0..FIMC_MAX_DEVS) - * @num_clocks: the number of clocks managed by this device instance - * @clock: clocks required for FIMC operation - * @regs: the mapped hardware registers - * @irq: FIMC interrupt number - * @irq_queue: interrupt handler waitqueue - * @v4l2_dev: root v4l2_device - * @m2m: memory-to-memory V4L2 device information - * @vid_cap: camera capture device information - * @state: flags used to synchronize m2m and capture mode operation - * @alloc_ctx: videobuf2 memory allocator context - * @pipeline: fimc video capture pipeline data structure - */ -struct fimc_dev { - spinlock_t slock; - struct mutex lock; - struct platform_device *pdev; - struct s5p_platform_fimc *pdata; - struct samsung_fimc_variant *variant; - u16 id; - u16 num_clocks; - struct clk *clock[MAX_FIMC_CLOCKS]; - void __iomem *regs; - int irq; - wait_queue_head_t irq_queue; - struct v4l2_device *v4l2_dev; - struct fimc_m2m_device m2m; - struct fimc_vid_cap vid_cap; - unsigned long state; - struct vb2_alloc_ctx *alloc_ctx; - struct fimc_pipeline pipeline; -}; - -/** - * fimc_ctx - the device context data - * @slock: spinlock protecting this data structure - * @s_frame: source frame properties - * @d_frame: destination frame properties - * @out_order_1p: output 1-plane YCBCR order - * @out_order_2p: output 2-plane YCBCR order - * @in_order_1p input 1-plane YCBCR order - * @in_order_2p: input 2-plane YCBCR order - * @in_path: input mode (DMA or camera) - * @out_path: output mode (DMA or FIFO) - * @scaler: image scaler properties - * @effect: image effect - * @rotation: image clockwise rotation in degrees - * @hflip: indicates image horizontal flip if set - * @vflip: indicates image vertical flip if set - * @flags: additional flags for image conversion - * @state: flags to keep track of user configuration - * @fimc_dev: the FIMC device this context applies to - * @m2m_ctx: memory-to-memory device context - * @fh: v4l2 file handle - * @ctrl_handler: v4l2 controls handler - * @ctrl_rotate image rotation control - * @ctrl_hflip horizontal flip control - * @ctrl_vflip vertical flip control - * @ctrl_alpha RGB alpha control - * @ctrls_rdy: true if the control handler is initialized - */ -struct fimc_ctx { - spinlock_t slock; - struct fimc_frame s_frame; - struct fimc_frame d_frame; - u32 out_order_1p; - u32 out_order_2p; - u32 in_order_1p; - u32 in_order_2p; - enum fimc_datapath in_path; - enum fimc_datapath out_path; - struct fimc_scaler scaler; - struct fimc_effect effect; - int rotation; - unsigned int hflip:1; - unsigned int vflip:1; - u32 flags; - u32 state; - struct fimc_dev *fimc_dev; - struct v4l2_m2m_ctx *m2m_ctx; - struct v4l2_fh fh; - struct v4l2_ctrl_handler ctrl_handler; - struct v4l2_ctrl *ctrl_rotate; - struct v4l2_ctrl *ctrl_hflip; - struct v4l2_ctrl *ctrl_vflip; - struct v4l2_ctrl *ctrl_alpha; - bool ctrls_rdy; -}; - -#define fh_to_ctx(__fh) container_of(__fh, struct fimc_ctx, fh) - -static inline void set_frame_bounds(struct fimc_frame *f, u32 width, u32 height) -{ - f->o_width = width; - f->o_height = height; - f->f_width = width; - f->f_height = height; -} - -static inline void set_frame_crop(struct fimc_frame *f, - u32 left, u32 top, u32 width, u32 height) -{ - f->offs_h = left; - f->offs_v = top; - f->width = width; - f->height = height; -} - -static inline u32 fimc_get_format_depth(struct fimc_fmt *ff) -{ - u32 i, depth = 0; - - if (ff != NULL) - for (i = 0; i < ff->colplanes; i++) - depth += ff->depth[i]; - return depth; -} - -static inline bool fimc_capture_active(struct fimc_dev *fimc) -{ - unsigned long flags; - bool ret; - - spin_lock_irqsave(&fimc->slock, flags); - ret = !!(fimc->state & (1 << ST_CAPT_RUN) || - fimc->state & (1 << ST_CAPT_PEND)); - spin_unlock_irqrestore(&fimc->slock, flags); - return ret; -} - -static inline void fimc_ctx_state_lock_set(u32 state, struct fimc_ctx *ctx) -{ - unsigned long flags; - - spin_lock_irqsave(&ctx->slock, flags); - ctx->state |= state; - spin_unlock_irqrestore(&ctx->slock, flags); -} - -static inline bool fimc_ctx_state_is_set(u32 mask, struct fimc_ctx *ctx) -{ - unsigned long flags; - bool ret; - - spin_lock_irqsave(&ctx->slock, flags); - ret = (ctx->state & mask) == mask; - spin_unlock_irqrestore(&ctx->slock, flags); - return ret; -} - -static inline int tiled_fmt(struct fimc_fmt *fmt) -{ - return fmt->fourcc == V4L2_PIX_FMT_NV12MT; -} - -/* Return the alpha component bit mask */ -static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt) -{ - switch (fmt->color) { - case S5P_FIMC_RGB444: return 0x0f; - case S5P_FIMC_RGB555: return 0x01; - case S5P_FIMC_RGB888: return 0xff; - default: return 0; - }; -} - -static inline void fimc_hw_clear_irq(struct fimc_dev *dev) -{ - u32 cfg = readl(dev->regs + S5P_CIGCTRL); - cfg |= S5P_CIGCTRL_IRQ_CLR; - writel(cfg, dev->regs + S5P_CIGCTRL); -} - -static inline void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on) -{ - u32 cfg = readl(dev->regs + S5P_CISCCTRL); - if (on) - cfg |= S5P_CISCCTRL_SCALERSTART; - else - cfg &= ~S5P_CISCCTRL_SCALERSTART; - writel(cfg, dev->regs + S5P_CISCCTRL); -} - -static inline void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on) -{ - u32 cfg = readl(dev->regs + S5P_MSCTRL); - if (on) - cfg |= S5P_MSCTRL_ENVID; - else - cfg &= ~S5P_MSCTRL_ENVID; - writel(cfg, dev->regs + S5P_MSCTRL); -} - -static inline void fimc_hw_dis_capture(struct fimc_dev *dev) -{ - u32 cfg = readl(dev->regs + S5P_CIIMGCPT); - cfg &= ~(S5P_CIIMGCPT_IMGCPTEN | S5P_CIIMGCPT_IMGCPTEN_SC); - writel(cfg, dev->regs + S5P_CIIMGCPT); -} - -/** - * fimc_hw_set_dma_seq - configure output DMA buffer sequence - * @mask: each bit corresponds to one of 32 output buffer registers set - * 1 to include buffer in the sequence, 0 to disable - * - * This function mask output DMA ring buffers, i.e. it allows to configure - * which of the output buffer address registers will be used by the DMA - * engine. - */ -static inline void fimc_hw_set_dma_seq(struct fimc_dev *dev, u32 mask) -{ - writel(mask, dev->regs + S5P_CIFCNTSEQ); -} - -static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx, - enum v4l2_buf_type type) -{ - struct fimc_frame *frame; - - if (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == type) { - if (fimc_ctx_state_is_set(FIMC_CTX_M2M, ctx)) - frame = &ctx->s_frame; - else - return ERR_PTR(-EINVAL); - } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == type) { - frame = &ctx->d_frame; - } else { - v4l2_err(ctx->fimc_dev->v4l2_dev, - "Wrong buffer/video queue type (%d)\n", type); - return ERR_PTR(-EINVAL); - } - - return frame; -} - -/* Return an index to the buffer actually being written. */ -static inline u32 fimc_hw_get_frame_index(struct fimc_dev *dev) -{ - u32 reg; - - if (dev->variant->has_cistatus2) { - reg = readl(dev->regs + S5P_CISTATUS2) & 0x3F; - return reg > 0 ? --reg : reg; - } else { - reg = readl(dev->regs + S5P_CISTATUS); - return (reg & S5P_CISTATUS_FRAMECNT_MASK) >> - S5P_CISTATUS_FRAMECNT_SHIFT; - } -} - -/* -----------------------------------------------------*/ -/* fimc-reg.c */ -void fimc_hw_reset(struct fimc_dev *fimc); -void fimc_hw_set_rotation(struct fimc_ctx *ctx); -void fimc_hw_set_target_format(struct fimc_ctx *ctx); -void fimc_hw_set_out_dma(struct fimc_ctx *ctx); -void fimc_hw_en_lastirq(struct fimc_dev *fimc, int enable); -void fimc_hw_en_irq(struct fimc_dev *fimc, int enable); -void fimc_hw_set_prescaler(struct fimc_ctx *ctx); -void fimc_hw_set_mainscaler(struct fimc_ctx *ctx); -void fimc_hw_en_capture(struct fimc_ctx *ctx); -void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active); -void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx); -void fimc_hw_set_in_dma(struct fimc_ctx *ctx); -void fimc_hw_set_input_path(struct fimc_ctx *ctx); -void fimc_hw_set_output_path(struct fimc_ctx *ctx); -void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr); -void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr, - int index); -int fimc_hw_set_camera_source(struct fimc_dev *fimc, - struct s5p_fimc_isp_info *cam); -int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f); -int fimc_hw_set_camera_polarity(struct fimc_dev *fimc, - struct s5p_fimc_isp_info *cam); -int fimc_hw_set_camera_type(struct fimc_dev *fimc, - struct s5p_fimc_isp_info *cam); - -/* -----------------------------------------------------*/ -/* fimc-core.c */ -int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv, - struct v4l2_fmtdesc *f); -int fimc_ctrls_create(struct fimc_ctx *ctx); -void fimc_ctrls_delete(struct fimc_ctx *ctx); -void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active); -void fimc_alpha_ctrl_update(struct fimc_ctx *ctx); -int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f); -void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height, - struct v4l2_pix_format_mplane *pix); -struct fimc_fmt *fimc_find_format(const u32 *pixelformat, const u32 *mbus_code, - unsigned int mask, int index); - -int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh, - int dw, int dh, int rotation); -int fimc_set_scaler_info(struct fimc_ctx *ctx); -int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags); -int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb, - struct fimc_frame *frame, struct fimc_addr *paddr); -void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f); -void fimc_set_yuv_order(struct fimc_ctx *ctx); -void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f); -void fimc_capture_irq_handler(struct fimc_dev *fimc, bool done); - -int fimc_register_m2m_device(struct fimc_dev *fimc, - struct v4l2_device *v4l2_dev); -void fimc_unregister_m2m_device(struct fimc_dev *fimc); -int fimc_register_driver(void); -void fimc_unregister_driver(void); - -/* -----------------------------------------------------*/ -/* fimc-capture.c */ -int fimc_register_capture_device(struct fimc_dev *fimc, - struct v4l2_device *v4l2_dev); -void fimc_unregister_capture_device(struct fimc_dev *fimc); -int fimc_capture_ctrls_create(struct fimc_dev *fimc); -int fimc_vid_cap_buf_queue(struct fimc_dev *fimc, - struct fimc_vid_buffer *fimc_vb); -void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification, - void *arg); -int fimc_capture_suspend(struct fimc_dev *fimc); -int fimc_capture_resume(struct fimc_dev *fimc); -int fimc_capture_config_update(struct fimc_ctx *ctx); - -/* Locking: the caller holds fimc->slock */ -static inline void fimc_activate_capture(struct fimc_ctx *ctx) -{ - fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled); - fimc_hw_en_capture(ctx); -} - -static inline void fimc_deactivate_capture(struct fimc_dev *fimc) -{ - fimc_hw_en_lastirq(fimc, true); - fimc_hw_dis_capture(fimc); - fimc_hw_enable_scaler(fimc, false); - fimc_hw_en_lastirq(fimc, false); -} - -/* - * Buffer list manipulation functions. Must be called with fimc.slock held. - */ - -/** - * fimc_active_queue_add - add buffer to the capture active buffers queue - * @buf: buffer to add to the active buffers list - */ -static inline void fimc_active_queue_add(struct fimc_vid_cap *vid_cap, - struct fimc_vid_buffer *buf) -{ - list_add_tail(&buf->list, &vid_cap->active_buf_q); - vid_cap->active_buf_cnt++; -} - -/** - * fimc_active_queue_pop - pop buffer from the capture active buffers queue - * - * The caller must assure the active_buf_q list is not empty. - */ -static inline struct fimc_vid_buffer *fimc_active_queue_pop( - struct fimc_vid_cap *vid_cap) -{ - struct fimc_vid_buffer *buf; - buf = list_entry(vid_cap->active_buf_q.next, - struct fimc_vid_buffer, list); - list_del(&buf->list); - vid_cap->active_buf_cnt--; - return buf; -} - -/** - * fimc_pending_queue_add - add buffer to the capture pending buffers queue - * @buf: buffer to add to the pending buffers list - */ -static inline void fimc_pending_queue_add(struct fimc_vid_cap *vid_cap, - struct fimc_vid_buffer *buf) -{ - list_add_tail(&buf->list, &vid_cap->pending_buf_q); -} - -/** - * fimc_pending_queue_pop - pop buffer from the capture pending buffers queue - * - * The caller must assure the pending_buf_q list is not empty. - */ -static inline struct fimc_vid_buffer *fimc_pending_queue_pop( - struct fimc_vid_cap *vid_cap) -{ - struct fimc_vid_buffer *buf; - buf = list_entry(vid_cap->pending_buf_q.next, - struct fimc_vid_buffer, list); - list_del(&buf->list); - return buf; -} - -#endif /* FIMC_CORE_H_ */ diff --git a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-mdevice.c b/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-mdevice.c deleted file mode 100644 index 62ed37e4..00000000 --- a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ /dev/null @@ -1,862 +0,0 @@ -/* - * S5P/EXYNOS4 SoC series camera host interface media device driver - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 2 of the License, - * or (at your option) any later version. - */ - -#include <linux/bug.h> -#include <linux/device.h> -#include <linux/errno.h> -#include <linux/i2c.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/types.h> -#include <linux/slab.h> -#include <media/v4l2-ctrls.h> -#include <media/media-device.h> - -#include "fimc-core.h" -#include "fimc-mdevice.h" -#include "mipi-csis.h" - -static int __fimc_md_set_camclk(struct fimc_md *fmd, - struct fimc_sensor_info *s_info, - bool on); -/** - * fimc_pipeline_prepare - update pipeline information with subdevice pointers - * @fimc: fimc device terminating the pipeline - * - * Caller holds the graph mutex. - */ -void fimc_pipeline_prepare(struct fimc_dev *fimc, struct media_entity *me) -{ - struct media_entity_graph graph; - struct v4l2_subdev *sd; - - media_entity_graph_walk_start(&graph, me); - - while ((me = media_entity_graph_walk_next(&graph))) { - if (media_entity_type(me) != MEDIA_ENT_T_V4L2_SUBDEV) - continue; - sd = media_entity_to_v4l2_subdev(me); - - if (sd->grp_id == SENSOR_GROUP_ID) - fimc->pipeline.sensor = sd; - else if (sd->grp_id == CSIS_GROUP_ID) - fimc->pipeline.csis = sd; - } -} - -/** - * __subdev_set_power - change power state of a single subdev - * @sd: subdevice to change power state for - * @on: 1 to enable power or 0 to disable - * - * Return result of s_power subdev operation or -ENXIO if sd argument - * is NULL. Return 0 if the subdevice does not implement s_power. - */ -static int __subdev_set_power(struct v4l2_subdev *sd, int on) -{ - int *use_count; - int ret; - - if (sd == NULL) - return -ENXIO; - - use_count = &sd->entity.use_count; - if (on && (*use_count)++ > 0) - return 0; - else if (!on && (*use_count == 0 || --(*use_count) > 0)) - return 0; - ret = v4l2_subdev_call(sd, core, s_power, on); - - return ret != -ENOIOCTLCMD ? ret : 0; -} - -/** - * fimc_pipeline_s_power - change power state of all pipeline subdevs - * @fimc: fimc device terminating the pipeline - * @state: 1 to enable power or 0 for power down - * - * Need to be called with the graph mutex held. - */ -int fimc_pipeline_s_power(struct fimc_dev *fimc, int state) -{ - int ret = 0; - - if (fimc->pipeline.sensor == NULL) - return -ENXIO; - - if (state) { - ret = __subdev_set_power(fimc->pipeline.csis, 1); - if (ret && ret != -ENXIO) - return ret; - return __subdev_set_power(fimc->pipeline.sensor, 1); - } - - ret = __subdev_set_power(fimc->pipeline.sensor, 0); - if (ret) - return ret; - ret = __subdev_set_power(fimc->pipeline.csis, 0); - - return ret == -ENXIO ? 0 : ret; -} - -/** - * __fimc_pipeline_initialize - update the pipeline information, enable power - * of all pipeline subdevs and the sensor clock - * @me: media entity to start graph walk with - * @prep: true to acquire sensor (and csis) subdevs - * - * This function must be called with the graph mutex held. - */ -static int __fimc_pipeline_initialize(struct fimc_dev *fimc, - struct media_entity *me, bool prep) -{ - int ret; - - if (prep) - fimc_pipeline_prepare(fimc, me); - if (fimc->pipeline.sensor == NULL) - return -EINVAL; - ret = fimc_md_set_camclk(fimc->pipeline.sensor, true); - if (ret) - return ret; - return fimc_pipeline_s_power(fimc, 1); -} - -int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me, - bool prep) -{ - int ret; - - mutex_lock(&me->parent->graph_mutex); - ret = __fimc_pipeline_initialize(fimc, me, prep); - mutex_unlock(&me->parent->graph_mutex); - - return ret; -} - -/** - * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power - * @fimc: fimc device terminating the pipeline - * - * Disable power of all subdevs in the pipeline and turn off the external - * sensor clock. - * Called with the graph mutex held. - */ -int __fimc_pipeline_shutdown(struct fimc_dev *fimc) -{ - int ret = 0; - - if (fimc->pipeline.sensor) { - ret = fimc_pipeline_s_power(fimc, 0); - fimc_md_set_camclk(fimc->pipeline.sensor, false); - } - return ret == -ENXIO ? 0 : ret; -} - -int fimc_pipeline_shutdown(struct fimc_dev *fimc) -{ - struct media_entity *me = &fimc->vid_cap.vfd->entity; - int ret; - - mutex_lock(&me->parent->graph_mutex); - ret = __fimc_pipeline_shutdown(fimc); - mutex_unlock(&me->parent->graph_mutex); - - return ret; -} - -/** - * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs - * @fimc: fimc device terminating the pipeline - * @on: passed as the s_stream call argument - */ -int fimc_pipeline_s_stream(struct fimc_dev *fimc, int on) -{ - struct fimc_pipeline *p = &fimc->pipeline; - int ret = 0; - - if (p->sensor == NULL) - return -ENODEV; - - if ((on && p->csis) || !on) - ret = v4l2_subdev_call(on ? p->csis : p->sensor, - video, s_stream, on); - if (ret < 0 && ret != -ENOIOCTLCMD) - return ret; - if ((!on && p->csis) || on) - ret = v4l2_subdev_call(on ? p->sensor : p->csis, - video, s_stream, on); - return ret == -ENOIOCTLCMD ? 0 : ret; -} - -/* - * Sensor subdevice helper functions - */ -static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd, - struct fimc_sensor_info *s_info) -{ - struct i2c_adapter *adapter; - struct v4l2_subdev *sd = NULL; - - if (!s_info || !fmd) - return NULL; - - adapter = i2c_get_adapter(s_info->pdata->i2c_bus_num); - if (!adapter) - return NULL; - sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter, - s_info->pdata->board_info, NULL); - if (IS_ERR_OR_NULL(sd)) { - i2c_put_adapter(adapter); - v4l2_err(&fmd->v4l2_dev, "Failed to acquire subdev\n"); - return NULL; - } - v4l2_set_subdev_hostdata(sd, s_info); - sd->grp_id = SENSOR_GROUP_ID; - - v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n", - s_info->pdata->board_info->type); - return sd; -} - -static void fimc_md_unregister_sensor(struct v4l2_subdev *sd) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct i2c_adapter *adapter; - - if (!client) - return; - v4l2_device_unregister_subdev(sd); - adapter = client->adapter; - i2c_unregister_device(client); - if (adapter) - i2c_put_adapter(adapter); -} - -static int fimc_md_register_sensor_entities(struct fimc_md *fmd) -{ - struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data; - struct fimc_dev *fd = NULL; - int num_clients, ret, i; - - /* - * Runtime resume one of the FIMC entities to make sure - * the sclk_cam clocks are not globally disabled. - */ - for (i = 0; !fd && i < ARRAY_SIZE(fmd->fimc); i++) - if (fmd->fimc[i]) - fd = fmd->fimc[i]; - if (!fd) - return -ENXIO; - ret = pm_runtime_get_sync(&fd->pdev->dev); - if (ret < 0) - return ret; - - WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor)); - num_clients = min_t(u32, pdata->num_clients, ARRAY_SIZE(fmd->sensor)); - - fmd->num_sensors = num_clients; - for (i = 0; i < num_clients; i++) { - fmd->sensor[i].pdata = &pdata->isp_info[i]; - ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true); - if (ret) - break; - fmd->sensor[i].subdev = - fimc_md_register_sensor(fmd, &fmd->sensor[i]); - ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], false); - if (ret) - break; - } - pm_runtime_put(&fd->pdev->dev); - return ret; -} - -/* - * MIPI CSIS and FIMC platform devices registration. - */ -static int fimc_register_callback(struct device *dev, void *p) -{ - struct fimc_dev *fimc = dev_get_drvdata(dev); - struct fimc_md *fmd = p; - int ret; - - if (!fimc || !fimc->pdev) - return 0; - if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS) - return 0; - - fmd->fimc[fimc->pdev->id] = fimc; - ret = fimc_register_m2m_device(fimc, &fmd->v4l2_dev); - if (ret) - return ret; - ret = fimc_register_capture_device(fimc, &fmd->v4l2_dev); - if (!ret) - fimc->vid_cap.user_subdev_api = fmd->user_subdev_api; - return ret; -} - -static int csis_register_callback(struct device *dev, void *p) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct platform_device *pdev; - struct fimc_md *fmd = p; - int id, ret; - - if (!sd) - return 0; - pdev = v4l2_get_subdevdata(sd); - if (!pdev || pdev->id < 0 || pdev->id >= CSIS_MAX_ENTITIES) - return 0; - v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name); - - id = pdev->id < 0 ? 0 : pdev->id; - fmd->csis[id].sd = sd; - sd->grp_id = CSIS_GROUP_ID; - ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); - if (ret) - v4l2_err(&fmd->v4l2_dev, - "Failed to register CSIS subdevice: %d\n", ret); - return ret; -} - -/** - * fimc_md_register_platform_entities - register FIMC and CSIS media entities - */ -static int fimc_md_register_platform_entities(struct fimc_md *fmd) -{ - struct device_driver *driver; - int ret; - - driver = driver_find(FIMC_MODULE_NAME, &platform_bus_type); - if (!driver) - return -ENODEV; - ret = driver_for_each_device(driver, NULL, fmd, - fimc_register_callback); - if (ret) - return ret; - - driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); - if (driver) - ret = driver_for_each_device(driver, NULL, fmd, - csis_register_callback); - return ret; -} - -static void fimc_md_unregister_entities(struct fimc_md *fmd) -{ - int i; - - for (i = 0; i < FIMC_MAX_DEVS; i++) { - if (fmd->fimc[i] == NULL) - continue; - fimc_unregister_m2m_device(fmd->fimc[i]); - fimc_unregister_capture_device(fmd->fimc[i]); - fmd->fimc[i] = NULL; - } - for (i = 0; i < CSIS_MAX_ENTITIES; i++) { - if (fmd->csis[i].sd == NULL) - continue; - v4l2_device_unregister_subdev(fmd->csis[i].sd); - fmd->csis[i].sd = NULL; - } - for (i = 0; i < fmd->num_sensors; i++) { - if (fmd->sensor[i].subdev == NULL) - continue; - fimc_md_unregister_sensor(fmd->sensor[i].subdev); - fmd->sensor[i].subdev = NULL; - } -} - -static int fimc_md_register_video_nodes(struct fimc_md *fmd) -{ - struct video_device *vdev; - int i, ret = 0; - - for (i = 0; i < FIMC_MAX_DEVS && !ret; i++) { - if (!fmd->fimc[i]) - continue; - - vdev = fmd->fimc[i]->m2m.vfd; - if (vdev) { - ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); - if (ret) - break; - v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n", - vdev->name, video_device_node_name(vdev)); - } - - vdev = fmd->fimc[i]->vid_cap.vfd; - if (vdev == NULL) - continue; - ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); - v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n", - vdev->name, video_device_node_name(vdev)); - } - - return ret; -} - -/** - * __fimc_md_create_fimc_links - create links to all FIMC entities - * @fmd: fimc media device - * @source: the source entity to create links to all fimc entities from - * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null - * @pad: the source entity pad index - * @fimc_id: index of the fimc device for which link should be enabled - */ -static int __fimc_md_create_fimc_links(struct fimc_md *fmd, - struct media_entity *source, - struct v4l2_subdev *sensor, - int pad, int fimc_id) -{ - struct fimc_sensor_info *s_info; - struct media_entity *sink; - unsigned int flags; - int ret, i; - - for (i = 0; i < FIMC_MAX_DEVS; i++) { - if (!fmd->fimc[i]) - break; - /* - * Some FIMC variants are not fitted with camera capture - * interface. Skip creating a link from sensor for those. - */ - if (sensor->grp_id == SENSOR_GROUP_ID && - !fmd->fimc[i]->variant->has_cam_if) - continue; - - flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0; - sink = &fmd->fimc[i]->vid_cap.subdev->entity; - ret = media_entity_create_link(source, pad, sink, - FIMC_SD_PAD_SINK, flags); - if (ret) - return ret; - - /* Notify FIMC capture subdev entity */ - ret = media_entity_call(sink, link_setup, &sink->pads[0], - &source->pads[pad], flags); - if (ret) - break; - - v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", - source->name, flags ? '=' : '-', sink->name); - - if (flags == 0) - continue; - s_info = v4l2_get_subdev_hostdata(sensor); - if (!WARN_ON(s_info == NULL)) { - unsigned long irq_flags; - spin_lock_irqsave(&fmd->slock, irq_flags); - s_info->host = fmd->fimc[i]; - spin_unlock_irqrestore(&fmd->slock, irq_flags); - } - } - return 0; -} - -/** - * fimc_md_create_links - create default links between registered entities - * - * Parallel interface sensor entities are connected directly to FIMC capture - * entities. The sensors using MIPI CSIS bus are connected through immutable - * link with CSI receiver entity specified by mux_id. Any registered CSIS - * entity has a link to each registered FIMC capture entity. Enabled links - * are created by default between each subsequent registered sensor and - * subsequent FIMC capture entity. The number of default active links is - * determined by the number of available sensors or FIMC entities, - * whichever is less. - */ -static int fimc_md_create_links(struct fimc_md *fmd) -{ - struct v4l2_subdev *sensor, *csis; - struct s5p_fimc_isp_info *pdata; - struct fimc_sensor_info *s_info; - struct media_entity *source, *sink; - int i, pad, fimc_id = 0; - int ret = 0; - u32 flags; - - for (i = 0; i < fmd->num_sensors; i++) { - if (fmd->sensor[i].subdev == NULL) - continue; - - sensor = fmd->sensor[i].subdev; - s_info = v4l2_get_subdev_hostdata(sensor); - if (!s_info || !s_info->pdata) - continue; - - source = NULL; - pdata = s_info->pdata; - - switch (pdata->bus_type) { - case FIMC_MIPI_CSI2: - if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES, - "Wrong CSI channel id: %d\n", pdata->mux_id)) - return -EINVAL; - - csis = fmd->csis[pdata->mux_id].sd; - if (WARN(csis == NULL, - "MIPI-CSI interface specified " - "but s5p-csis module is not loaded!\n")) - return -EINVAL; - - ret = media_entity_create_link(&sensor->entity, 0, - &csis->entity, CSIS_PAD_SINK, - MEDIA_LNK_FL_IMMUTABLE | - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - - v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]", - sensor->entity.name, csis->entity.name); - - source = &csis->entity; - pad = CSIS_PAD_SOURCE; - break; - - case FIMC_ITU_601...FIMC_ITU_656: - source = &sensor->entity; - pad = 0; - break; - - default: - v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n", - pdata->bus_type); - return -EINVAL; - } - if (source == NULL) - continue; - - ret = __fimc_md_create_fimc_links(fmd, source, sensor, pad, - fimc_id++); - } - /* Create immutable links between each FIMC's subdev and video node */ - flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED; - for (i = 0; i < FIMC_MAX_DEVS; i++) { - if (!fmd->fimc[i]) - continue; - source = &fmd->fimc[i]->vid_cap.subdev->entity; - sink = &fmd->fimc[i]->vid_cap.vfd->entity; - ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, - sink, 0, flags); - if (ret) - break; - } - - return ret; -} - -/* - * The peripheral sensor clock management. - */ -static int fimc_md_get_clocks(struct fimc_md *fmd) -{ - char clk_name[32]; - struct clk *clock; - int i; - - for (i = 0; i < FIMC_MAX_CAMCLKS; i++) { - snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i); - clock = clk_get(NULL, clk_name); - if (IS_ERR_OR_NULL(clock)) { - v4l2_err(&fmd->v4l2_dev, "Failed to get clock: %s", - clk_name); - return -ENXIO; - } - fmd->camclk[i].clock = clock; - } - return 0; -} - -static void fimc_md_put_clocks(struct fimc_md *fmd) -{ - int i = FIMC_MAX_CAMCLKS; - - while (--i >= 0) { - if (IS_ERR_OR_NULL(fmd->camclk[i].clock)) - continue; - clk_put(fmd->camclk[i].clock); - fmd->camclk[i].clock = NULL; - } -} - -static int __fimc_md_set_camclk(struct fimc_md *fmd, - struct fimc_sensor_info *s_info, - bool on) -{ - struct s5p_fimc_isp_info *pdata = s_info->pdata; - struct fimc_camclk_info *camclk; - int ret = 0; - - if (WARN_ON(pdata->clk_id >= FIMC_MAX_CAMCLKS) || fmd == NULL) - return -EINVAL; - - if (s_info->clk_on == on) - return 0; - camclk = &fmd->camclk[pdata->clk_id]; - - dbg("camclk %d, f: %lu, clk: %p, on: %d", - pdata->clk_id, pdata->clk_frequency, camclk, on); - - if (on) { - if (camclk->use_count > 0 && - camclk->frequency != pdata->clk_frequency) - return -EINVAL; - - if (camclk->use_count++ == 0) { - clk_set_rate(camclk->clock, pdata->clk_frequency); - camclk->frequency = pdata->clk_frequency; - ret = clk_enable(camclk->clock); - } - s_info->clk_on = 1; - dbg("Enabled camclk %d: f: %lu", pdata->clk_id, - clk_get_rate(camclk->clock)); - - return ret; - } - - if (WARN_ON(camclk->use_count == 0)) - return 0; - - if (--camclk->use_count == 0) { - clk_disable(camclk->clock); - s_info->clk_on = 0; - dbg("Disabled camclk %d", pdata->clk_id); - } - return ret; -} - -/** - * fimc_md_set_camclk - peripheral sensor clock setup - * @sd: sensor subdev to configure sclk_cam clock for - * @on: 1 to enable or 0 to disable the clock - * - * There are 2 separate clock outputs available in the SoC for external - * image processors. These clocks are shared between all registered FIMC - * devices to which sensors can be attached, either directly or through - * the MIPI CSI receiver. The clock is allowed here to be used by - * multiple sensors concurrently if they use same frequency. - * The per sensor subdev clk_on attribute helps to synchronize accesses - * to the sclk_cam clocks from the video and media device nodes. - * This function should only be called when the graph mutex is held. - */ -int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on) -{ - struct fimc_sensor_info *s_info = v4l2_get_subdev_hostdata(sd); - struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity); - - return __fimc_md_set_camclk(fmd, s_info, on); -} - -static int fimc_md_link_notify(struct media_pad *source, - struct media_pad *sink, u32 flags) -{ - struct v4l2_subdev *sd; - struct fimc_dev *fimc; - int ret = 0; - - if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) - return 0; - - sd = media_entity_to_v4l2_subdev(sink->entity); - fimc = v4l2_get_subdevdata(sd); - - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ret = __fimc_pipeline_shutdown(fimc); - fimc->pipeline.sensor = NULL; - fimc->pipeline.csis = NULL; - - mutex_lock(&fimc->lock); - fimc_ctrls_delete(fimc->vid_cap.ctx); - mutex_unlock(&fimc->lock); - return ret; - } - /* - * Link activation. Enable power of pipeline elements only if the - * pipeline is already in use, i.e. its video node is opened. - * Recreate the controls destroyed during the link deactivation. - */ - mutex_lock(&fimc->lock); - if (fimc->vid_cap.refcnt > 0) { - ret = __fimc_pipeline_initialize(fimc, source->entity, true); - if (!ret) - ret = fimc_capture_ctrls_create(fimc); - } - mutex_unlock(&fimc->lock); - - return ret ? -EPIPE : ret; -} - -static ssize_t fimc_md_sysfs_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - struct fimc_md *fmd = platform_get_drvdata(pdev); - - if (fmd->user_subdev_api) - return strlcpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE); - - return strlcpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE); -} - -static ssize_t fimc_md_sysfs_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct platform_device *pdev = to_platform_device(dev); - struct fimc_md *fmd = platform_get_drvdata(pdev); - bool subdev_api; - int i; - - if (!strcmp(buf, "vid-dev\n")) - subdev_api = false; - else if (!strcmp(buf, "sub-dev\n")) - subdev_api = true; - else - return count; - - fmd->user_subdev_api = subdev_api; - for (i = 0; i < FIMC_MAX_DEVS; i++) - if (fmd->fimc[i]) - fmd->fimc[i]->vid_cap.user_subdev_api = subdev_api; - return count; -} -/* - * This device attribute is to select video pipeline configuration method. - * There are following valid values: - * vid-dev - for V4L2 video node API only, subdevice will be configured - * by the host driver. - * sub-dev - for media controller API, subdevs must be configured in user - * space before starting streaming. - */ -static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO, - fimc_md_sysfs_show, fimc_md_sysfs_store); - -static int __devinit fimc_md_probe(struct platform_device *pdev) -{ - struct v4l2_device *v4l2_dev; - struct fimc_md *fmd; - int ret; - - fmd = devm_kzalloc(&pdev->dev, sizeof(*fmd), GFP_KERNEL); - if (!fmd) - return -ENOMEM; - - spin_lock_init(&fmd->slock); - fmd->pdev = pdev; - - strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC", - sizeof(fmd->media_dev.model)); - fmd->media_dev.link_notify = fimc_md_link_notify; - fmd->media_dev.dev = &pdev->dev; - - v4l2_dev = &fmd->v4l2_dev; - v4l2_dev->mdev = &fmd->media_dev; - v4l2_dev->notify = fimc_sensor_notify; - snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s", - dev_name(&pdev->dev)); - - ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev); - if (ret < 0) { - v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); - return ret; - } - ret = media_device_register(&fmd->media_dev); - if (ret < 0) { - v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret); - goto err2; - } - ret = fimc_md_get_clocks(fmd); - if (ret) - goto err3; - - fmd->user_subdev_api = false; - ret = fimc_md_register_platform_entities(fmd); - if (ret) - goto err3; - - if (pdev->dev.platform_data) { - ret = fimc_md_register_sensor_entities(fmd); - if (ret) - goto err3; - } - ret = fimc_md_create_links(fmd); - if (ret) - goto err3; - ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev); - if (ret) - goto err3; - ret = fimc_md_register_video_nodes(fmd); - if (ret) - goto err3; - - ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode); - if (!ret) { - platform_set_drvdata(pdev, fmd); - return 0; - } -err3: - media_device_unregister(&fmd->media_dev); - fimc_md_put_clocks(fmd); - fimc_md_unregister_entities(fmd); -err2: - v4l2_device_unregister(&fmd->v4l2_dev); - return ret; -} - -static int __devexit fimc_md_remove(struct platform_device *pdev) -{ - struct fimc_md *fmd = platform_get_drvdata(pdev); - - if (!fmd) - return 0; - device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); - fimc_md_unregister_entities(fmd); - media_device_unregister(&fmd->media_dev); - fimc_md_put_clocks(fmd); - return 0; -} - -static struct platform_driver fimc_md_driver = { - .probe = fimc_md_probe, - .remove = __devexit_p(fimc_md_remove), - .driver = { - .name = "s5p-fimc-md", - .owner = THIS_MODULE, - } -}; - -int __init fimc_md_init(void) -{ - int ret; - request_module("s5p-csis"); - ret = fimc_register_driver(); - if (ret) - return ret; - return platform_driver_register(&fimc_md_driver); -} -void __exit fimc_md_exit(void) -{ - platform_driver_unregister(&fimc_md_driver); - fimc_unregister_driver(); -} - -module_init(fimc_md_init); -module_exit(fimc_md_exit); - -MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); -MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("2.0.1"); diff --git a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-mdevice.h b/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-mdevice.h deleted file mode 100644 index da378082..00000000 --- a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-mdevice.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef FIMC_MDEVICE_H_ -#define FIMC_MDEVICE_H_ - -#include <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/mutex.h> -#include <media/media-device.h> -#include <media/media-entity.h> -#include <media/v4l2-device.h> -#include <media/v4l2-subdev.h> - -#include "fimc-core.h" -#include "mipi-csis.h" - -/* Group IDs of sensor, MIPI CSIS and the writeback subdevs. */ -#define SENSOR_GROUP_ID (1 << 8) -#define CSIS_GROUP_ID (1 << 9) -#define WRITEBACK_GROUP_ID (1 << 10) - -#define FIMC_MAX_SENSORS 8 -#define FIMC_MAX_CAMCLKS 2 - -struct fimc_csis_info { - struct v4l2_subdev *sd; - int id; -}; - -struct fimc_camclk_info { - struct clk *clock; - int use_count; - unsigned long frequency; -}; - -/** - * struct fimc_sensor_info - image data source subdev information - * @pdata: sensor's atrributes passed as media device's platform data - * @subdev: image sensor v4l2 subdev - * @host: fimc device the sensor is currently linked to - * @clk_on: sclk_cam clock's state associated with this subdev - * - * This data structure applies to image sensor and the writeback subdevs. - */ -struct fimc_sensor_info { - struct s5p_fimc_isp_info *pdata; - struct v4l2_subdev *subdev; - struct fimc_dev *host; - bool clk_on; -}; - -/** - * struct fimc_md - fimc media device information - * @csis: MIPI CSIS subdevs data - * @sensor: array of registered sensor subdevs - * @num_sensors: actual number of registered sensors - * @camclk: external sensor clock information - * @fimc: array of registered fimc devices - * @media_dev: top level media device - * @v4l2_dev: top level v4l2_device holding up the subdevs - * @pdev: platform device this media device is hooked up into - * @user_subdev_api: true if subdevs are not configured by the host driver - * @slock: spinlock protecting @sensor array - */ -struct fimc_md { - struct fimc_csis_info csis[CSIS_MAX_ENTITIES]; - struct fimc_sensor_info sensor[FIMC_MAX_SENSORS]; - int num_sensors; - struct fimc_camclk_info camclk[FIMC_MAX_CAMCLKS]; - struct fimc_dev *fimc[FIMC_MAX_DEVS]; - struct media_device media_dev; - struct v4l2_device v4l2_dev; - struct platform_device *pdev; - bool user_subdev_api; - spinlock_t slock; -}; - -#define is_subdev_pad(pad) (pad == NULL || \ - media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) - -#define me_subtype(me) \ - ((me->type) & (MEDIA_ENT_TYPE_MASK | MEDIA_ENT_SUBTYPE_MASK)) - -#define subdev_has_devnode(__sd) (__sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE) - -static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me) -{ - return me->parent == NULL ? NULL : - container_of(me->parent, struct fimc_md, media_dev); -} - -static inline void fimc_md_graph_lock(struct fimc_dev *fimc) -{ - BUG_ON(fimc->vid_cap.vfd == NULL); - mutex_lock(&fimc->vid_cap.vfd->entity.parent->graph_mutex); -} - -static inline void fimc_md_graph_unlock(struct fimc_dev *fimc) -{ - BUG_ON(fimc->vid_cap.vfd == NULL); - mutex_unlock(&fimc->vid_cap.vfd->entity.parent->graph_mutex); -} - -int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on); -void fimc_pipeline_prepare(struct fimc_dev *fimc, struct media_entity *me); -int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me, - bool resume); -int fimc_pipeline_shutdown(struct fimc_dev *fimc); -int fimc_pipeline_s_power(struct fimc_dev *fimc, int state); -int fimc_pipeline_s_stream(struct fimc_dev *fimc, int state); - -#endif diff --git a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-reg.c b/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-reg.c deleted file mode 100644 index 15466d05..00000000 --- a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/fimc-reg.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - * Register interface file for Samsung Camera Interface (FIMC) driver - * - * Copyright (c) 2010 Samsung Electronics - * - * Sylwester Nawrocki, s.nawrocki@samsung.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include <linux/io.h> -#include <linux/delay.h> -#include <mach/map.h> -#include <media/s5p_fimc.h> - -#include "fimc-core.h" - - -void fimc_hw_reset(struct fimc_dev *dev) -{ - u32 cfg; - - cfg = readl(dev->regs + S5P_CISRCFMT); - cfg |= S5P_CISRCFMT_ITU601_8BIT; - writel(cfg, dev->regs + S5P_CISRCFMT); - - /* Software reset. */ - cfg = readl(dev->regs + S5P_CIGCTRL); - cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL); - writel(cfg, dev->regs + S5P_CIGCTRL); - udelay(10); - - cfg = readl(dev->regs + S5P_CIGCTRL); - cfg &= ~S5P_CIGCTRL_SWRST; - writel(cfg, dev->regs + S5P_CIGCTRL); - - if (dev->variant->out_buf_count > 4) - fimc_hw_set_dma_seq(dev, 0xF); -} - -static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx) -{ - u32 flip = S5P_MSCTRL_FLIP_NORMAL; - - if (ctx->hflip) - flip = S5P_MSCTRL_FLIP_X_MIRROR; - if (ctx->vflip) - flip = S5P_MSCTRL_FLIP_Y_MIRROR; - - if (ctx->rotation <= 90) - return flip; - - return (flip ^ S5P_MSCTRL_FLIP_180) & S5P_MSCTRL_FLIP_180; -} - -static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx) -{ - u32 flip = S5P_CITRGFMT_FLIP_NORMAL; - - if (ctx->hflip) - flip |= S5P_CITRGFMT_FLIP_X_MIRROR; - if (ctx->vflip) - flip |= S5P_CITRGFMT_FLIP_Y_MIRROR; - - if (ctx->rotation <= 90) - return flip; - - return (flip ^ S5P_CITRGFMT_FLIP_180) & S5P_CITRGFMT_FLIP_180; -} - -void fimc_hw_set_rotation(struct fimc_ctx *ctx) -{ - u32 cfg, flip; - struct fimc_dev *dev = ctx->fimc_dev; - - cfg = readl(dev->regs + S5P_CITRGFMT); - cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90 | - S5P_CITRGFMT_FLIP_180); - - /* - * The input and output rotator cannot work simultaneously. - * Use the output rotator in output DMA mode or the input rotator - * in direct fifo output mode. - */ - if (ctx->rotation == 90 || ctx->rotation == 270) { - if (ctx->out_path == FIMC_LCDFIFO) - cfg |= S5P_CITRGFMT_INROT90; - else - cfg |= S5P_CITRGFMT_OUTROT90; - } - - if (ctx->out_path == FIMC_DMA) { - cfg |= fimc_hw_get_target_flip(ctx); - writel(cfg, dev->regs + S5P_CITRGFMT); - } else { - /* LCD FIFO path */ - flip = readl(dev->regs + S5P_MSCTRL); - flip &= ~S5P_MSCTRL_FLIP_MASK; - flip |= fimc_hw_get_in_flip(ctx); - writel(flip, dev->regs + S5P_MSCTRL); - } -} - -void fimc_hw_set_target_format(struct fimc_ctx *ctx) -{ - u32 cfg; - struct fimc_dev *dev = ctx->fimc_dev; - struct fimc_frame *frame = &ctx->d_frame; - - dbg("w= %d, h= %d color: %d", frame->width, - frame->height, frame->fmt->color); - - cfg = readl(dev->regs + S5P_CITRGFMT); - cfg &= ~(S5P_CITRGFMT_FMT_MASK | S5P_CITRGFMT_HSIZE_MASK | - S5P_CITRGFMT_VSIZE_MASK); - - switch (frame->fmt->color) { - case S5P_FIMC_RGB444...S5P_FIMC_RGB888: - cfg |= S5P_CITRGFMT_RGB; - break; - case S5P_FIMC_YCBCR420: - cfg |= S5P_CITRGFMT_YCBCR420; - break; - case S5P_FIMC_YCBYCR422...S5P_FIMC_CRYCBY422: - if (frame->fmt->colplanes == 1) - cfg |= S5P_CITRGFMT_YCBCR422_1P; - else - cfg |= S5P_CITRGFMT_YCBCR422; - break; - default: - break; - } - - if (ctx->rotation == 90 || ctx->rotation == 270) { - cfg |= S5P_CITRGFMT_HSIZE(frame->height); - cfg |= S5P_CITRGFMT_VSIZE(frame->width); - } else { - - cfg |= S5P_CITRGFMT_HSIZE(frame->width); - cfg |= S5P_CITRGFMT_VSIZE(frame->height); - } - - writel(cfg, dev->regs + S5P_CITRGFMT); - - cfg = readl(dev->regs + S5P_CITAREA) & ~S5P_CITAREA_MASK; - cfg |= (frame->width * frame->height); - writel(cfg, dev->regs + S5P_CITAREA); -} - -static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - struct fimc_frame *frame = &ctx->d_frame; - u32 cfg; - - cfg = S5P_ORIG_SIZE_HOR(frame->f_width); - cfg |= S5P_ORIG_SIZE_VER(frame->f_height); - writel(cfg, dev->regs + S5P_ORGOSIZE); - - /* Select color space conversion equation (HD/SD size).*/ - cfg = readl(dev->regs + S5P_CIGCTRL); - if (frame->f_width >= 1280) /* HD */ - cfg |= S5P_CIGCTRL_CSC_ITU601_709; - else /* SD */ - cfg &= ~S5P_CIGCTRL_CSC_ITU601_709; - writel(cfg, dev->regs + S5P_CIGCTRL); - -} - -void fimc_hw_set_out_dma(struct fimc_ctx *ctx) -{ - u32 cfg; - struct fimc_dev *dev = ctx->fimc_dev; - struct fimc_frame *frame = &ctx->d_frame; - struct fimc_dma_offset *offset = &frame->dma_offset; - struct fimc_fmt *fmt = frame->fmt; - - /* Set the input dma offsets. */ - cfg = 0; - cfg |= S5P_CIO_OFFS_HOR(offset->y_h); - cfg |= S5P_CIO_OFFS_VER(offset->y_v); - writel(cfg, dev->regs + S5P_CIOYOFF); - - cfg = 0; - cfg |= S5P_CIO_OFFS_HOR(offset->cb_h); - cfg |= S5P_CIO_OFFS_VER(offset->cb_v); - writel(cfg, dev->regs + S5P_CIOCBOFF); - - cfg = 0; - cfg |= S5P_CIO_OFFS_HOR(offset->cr_h); - cfg |= S5P_CIO_OFFS_VER(offset->cr_v); - writel(cfg, dev->regs + S5P_CIOCROFF); - - fimc_hw_set_out_dma_size(ctx); - - /* Configure chroma components order. */ - cfg = readl(dev->regs + S5P_CIOCTRL); - - cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK | - S5P_CIOCTRL_YCBCR_PLANE_MASK | S5P_CIOCTRL_RGB16FMT_MASK); - - if (fmt->colplanes == 1) - cfg |= ctx->out_order_1p; - else if (fmt->colplanes == 2) - cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE; - else if (fmt->colplanes == 3) - cfg |= S5P_CIOCTRL_YCBCR_3PLANE; - - if (fmt->color == S5P_FIMC_RGB565) - cfg |= S5P_CIOCTRL_RGB565; - else if (fmt->color == S5P_FIMC_RGB555) - cfg |= S5P_CIOCTRL_ARGB1555; - else if (fmt->color == S5P_FIMC_RGB444) - cfg |= S5P_CIOCTRL_ARGB4444; - - writel(cfg, dev->regs + S5P_CIOCTRL); -} - -static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable) -{ - u32 cfg = readl(dev->regs + S5P_ORGISIZE); - if (enable) - cfg |= S5P_CIREAL_ISIZE_AUTOLOAD_EN; - else - cfg &= ~S5P_CIREAL_ISIZE_AUTOLOAD_EN; - writel(cfg, dev->regs + S5P_ORGISIZE); -} - -void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable) -{ - u32 cfg = readl(dev->regs + S5P_CIOCTRL); - if (enable) - cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE; - else - cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE; - writel(cfg, dev->regs + S5P_CIOCTRL); -} - -void fimc_hw_set_prescaler(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - struct fimc_scaler *sc = &ctx->scaler; - u32 cfg, shfactor; - - shfactor = 10 - (sc->hfactor + sc->vfactor); - - cfg = S5P_CISCPRERATIO_SHFACTOR(shfactor); - cfg |= S5P_CISCPRERATIO_HOR(sc->pre_hratio); - cfg |= S5P_CISCPRERATIO_VER(sc->pre_vratio); - writel(cfg, dev->regs + S5P_CISCPRERATIO); - - cfg = S5P_CISCPREDST_WIDTH(sc->pre_dst_width); - cfg |= S5P_CISCPREDST_HEIGHT(sc->pre_dst_height); - writel(cfg, dev->regs + S5P_CISCPREDST); -} - -static void fimc_hw_set_scaler(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - struct fimc_scaler *sc = &ctx->scaler; - struct fimc_frame *src_frame = &ctx->s_frame; - struct fimc_frame *dst_frame = &ctx->d_frame; - - u32 cfg = readl(dev->regs + S5P_CISCCTRL); - - cfg &= ~(S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE | - S5P_CISCCTRL_SCALEUP_H | S5P_CISCCTRL_SCALEUP_V | - S5P_CISCCTRL_SCALERBYPASS | S5P_CISCCTRL_ONE2ONE | - S5P_CISCCTRL_INRGB_FMT_MASK | S5P_CISCCTRL_OUTRGB_FMT_MASK | - S5P_CISCCTRL_INTERLACE | S5P_CISCCTRL_RGB_EXT); - - if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW)) - cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE); - - if (!sc->enabled) - cfg |= S5P_CISCCTRL_SCALERBYPASS; - - if (sc->scaleup_h) - cfg |= S5P_CISCCTRL_SCALEUP_H; - - if (sc->scaleup_v) - cfg |= S5P_CISCCTRL_SCALEUP_V; - - if (sc->copy_mode) - cfg |= S5P_CISCCTRL_ONE2ONE; - - if (ctx->in_path == FIMC_DMA) { - switch (src_frame->fmt->color) { - case S5P_FIMC_RGB565: - cfg |= S5P_CISCCTRL_INRGB_FMT_RGB565; - break; - case S5P_FIMC_RGB666: - cfg |= S5P_CISCCTRL_INRGB_FMT_RGB666; - break; - case S5P_FIMC_RGB888: - cfg |= S5P_CISCCTRL_INRGB_FMT_RGB888; - break; - } - } - - if (ctx->out_path == FIMC_DMA) { - u32 color = dst_frame->fmt->color; - - if (color >= S5P_FIMC_RGB444 && color <= S5P_FIMC_RGB565) - cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB565; - else if (color == S5P_FIMC_RGB666) - cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB666; - else if (color == S5P_FIMC_RGB888) - cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888; - } else { - cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888; - - if (ctx->flags & FIMC_SCAN_MODE_INTERLACED) - cfg |= S5P_CISCCTRL_INTERLACE; - } - - writel(cfg, dev->regs + S5P_CISCCTRL); -} - -void fimc_hw_set_mainscaler(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - struct samsung_fimc_variant *variant = dev->variant; - struct fimc_scaler *sc = &ctx->scaler; - u32 cfg; - - dbg("main_hratio= 0x%X main_vratio= 0x%X", - sc->main_hratio, sc->main_vratio); - - fimc_hw_set_scaler(ctx); - - cfg = readl(dev->regs + S5P_CISCCTRL); - cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK); - - if (variant->has_mainscaler_ext) { - cfg |= S5P_CISCCTRL_MHRATIO_EXT(sc->main_hratio); - cfg |= S5P_CISCCTRL_MVRATIO_EXT(sc->main_vratio); - writel(cfg, dev->regs + S5P_CISCCTRL); - - cfg = readl(dev->regs + S5P_CIEXTEN); - - cfg &= ~(S5P_CIEXTEN_MVRATIO_EXT_MASK | - S5P_CIEXTEN_MHRATIO_EXT_MASK); - cfg |= S5P_CIEXTEN_MHRATIO_EXT(sc->main_hratio); - cfg |= S5P_CIEXTEN_MVRATIO_EXT(sc->main_vratio); - writel(cfg, dev->regs + S5P_CIEXTEN); - } else { - cfg |= S5P_CISCCTRL_MHRATIO(sc->main_hratio); - cfg |= S5P_CISCCTRL_MVRATIO(sc->main_vratio); - writel(cfg, dev->regs + S5P_CISCCTRL); - } -} - -void fimc_hw_en_capture(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - - u32 cfg = readl(dev->regs + S5P_CIIMGCPT); - - if (ctx->out_path == FIMC_DMA) { - /* one shot mode */ - cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_IMGCPTEN; - } else { - /* Continuous frame capture mode (freerun). */ - cfg &= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE | - S5P_CIIMGCPT_CPT_FRMOD_CNT); - cfg |= S5P_CIIMGCPT_IMGCPTEN; - } - - if (ctx->scaler.enabled) - cfg |= S5P_CIIMGCPT_IMGCPTEN_SC; - - writel(cfg | S5P_CIIMGCPT_IMGCPTEN, dev->regs + S5P_CIIMGCPT); -} - -void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active) -{ - struct fimc_dev *dev = ctx->fimc_dev; - struct fimc_effect *effect = &ctx->effect; - u32 cfg = 0; - - if (active) { - cfg |= S5P_CIIMGEFF_IE_SC_AFTER | S5P_CIIMGEFF_IE_ENABLE; - cfg |= effect->type; - if (effect->type == S5P_FIMC_EFFECT_ARBITRARY) { - cfg |= S5P_CIIMGEFF_PAT_CB(effect->pat_cb); - cfg |= S5P_CIIMGEFF_PAT_CR(effect->pat_cr); - } - } - - writel(cfg, dev->regs + S5P_CIIMGEFF); -} - -void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - struct fimc_frame *frame = &ctx->d_frame; - u32 cfg; - - if (!(frame->fmt->flags & FMT_HAS_ALPHA)) - return; - - cfg = readl(dev->regs + S5P_CIOCTRL); - cfg &= ~S5P_CIOCTRL_ALPHA_OUT_MASK; - cfg |= (frame->alpha << 4); - writel(cfg, dev->regs + S5P_CIOCTRL); -} - -static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - struct fimc_frame *frame = &ctx->s_frame; - u32 cfg_o = 0; - u32 cfg_r = 0; - - if (FIMC_LCDFIFO == ctx->out_path) - cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN; - - cfg_o |= S5P_ORIG_SIZE_HOR(frame->f_width); - cfg_o |= S5P_ORIG_SIZE_VER(frame->f_height); - cfg_r |= S5P_CIREAL_ISIZE_WIDTH(frame->width); - cfg_r |= S5P_CIREAL_ISIZE_HEIGHT(frame->height); - - writel(cfg_o, dev->regs + S5P_ORGISIZE); - writel(cfg_r, dev->regs + S5P_CIREAL_ISIZE); -} - -void fimc_hw_set_in_dma(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - struct fimc_frame *frame = &ctx->s_frame; - struct fimc_dma_offset *offset = &frame->dma_offset; - u32 cfg; - - /* Set the pixel offsets. */ - cfg = S5P_CIO_OFFS_HOR(offset->y_h); - cfg |= S5P_CIO_OFFS_VER(offset->y_v); - writel(cfg, dev->regs + S5P_CIIYOFF); - - cfg = S5P_CIO_OFFS_HOR(offset->cb_h); - cfg |= S5P_CIO_OFFS_VER(offset->cb_v); - writel(cfg, dev->regs + S5P_CIICBOFF); - - cfg = S5P_CIO_OFFS_HOR(offset->cr_h); - cfg |= S5P_CIO_OFFS_VER(offset->cr_v); - writel(cfg, dev->regs + S5P_CIICROFF); - - /* Input original and real size. */ - fimc_hw_set_in_dma_size(ctx); - - /* Use DMA autoload only in FIFO mode. */ - fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO); - - /* Set the input DMA to process single frame only. */ - cfg = readl(dev->regs + S5P_MSCTRL); - cfg &= ~(S5P_MSCTRL_INFORMAT_MASK - | S5P_MSCTRL_IN_BURST_COUNT_MASK - | S5P_MSCTRL_INPUT_MASK - | S5P_MSCTRL_C_INT_IN_MASK - | S5P_MSCTRL_2P_IN_ORDER_MASK); - - cfg |= (S5P_MSCTRL_IN_BURST_COUNT(4) - | S5P_MSCTRL_INPUT_MEMORY - | S5P_MSCTRL_FIFO_CTRL_FULL); - - switch (frame->fmt->color) { - case S5P_FIMC_RGB565...S5P_FIMC_RGB888: - cfg |= S5P_MSCTRL_INFORMAT_RGB; - break; - case S5P_FIMC_YCBCR420: - cfg |= S5P_MSCTRL_INFORMAT_YCBCR420; - - if (frame->fmt->colplanes == 2) - cfg |= ctx->in_order_2p | S5P_MSCTRL_C_INT_IN_2PLANE; - else - cfg |= S5P_MSCTRL_C_INT_IN_3PLANE; - - break; - case S5P_FIMC_YCBYCR422...S5P_FIMC_CRYCBY422: - if (frame->fmt->colplanes == 1) { - cfg |= ctx->in_order_1p - | S5P_MSCTRL_INFORMAT_YCBCR422_1P; - } else { - cfg |= S5P_MSCTRL_INFORMAT_YCBCR422; - - if (frame->fmt->colplanes == 2) - cfg |= ctx->in_order_2p - | S5P_MSCTRL_C_INT_IN_2PLANE; - else - cfg |= S5P_MSCTRL_C_INT_IN_3PLANE; - } - break; - default: - break; - } - - writel(cfg, dev->regs + S5P_MSCTRL); - - /* Input/output DMA linear/tiled mode. */ - cfg = readl(dev->regs + S5P_CIDMAPARAM); - cfg &= ~S5P_CIDMAPARAM_TILE_MASK; - - if (tiled_fmt(ctx->s_frame.fmt)) - cfg |= S5P_CIDMAPARAM_R_64X32; - - if (tiled_fmt(ctx->d_frame.fmt)) - cfg |= S5P_CIDMAPARAM_W_64X32; - - writel(cfg, dev->regs + S5P_CIDMAPARAM); -} - - -void fimc_hw_set_input_path(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - - u32 cfg = readl(dev->regs + S5P_MSCTRL); - cfg &= ~S5P_MSCTRL_INPUT_MASK; - - if (ctx->in_path == FIMC_DMA) - cfg |= S5P_MSCTRL_INPUT_MEMORY; - else - cfg |= S5P_MSCTRL_INPUT_EXTCAM; - - writel(cfg, dev->regs + S5P_MSCTRL); -} - -void fimc_hw_set_output_path(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - - u32 cfg = readl(dev->regs + S5P_CISCCTRL); - cfg &= ~S5P_CISCCTRL_LCDPATHEN_FIFO; - if (ctx->out_path == FIMC_LCDFIFO) - cfg |= S5P_CISCCTRL_LCDPATHEN_FIFO; - writel(cfg, dev->regs + S5P_CISCCTRL); -} - -void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr) -{ - u32 cfg = readl(dev->regs + S5P_CIREAL_ISIZE); - cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS; - writel(cfg, dev->regs + S5P_CIREAL_ISIZE); - - writel(paddr->y, dev->regs + S5P_CIIYSA(0)); - writel(paddr->cb, dev->regs + S5P_CIICBSA(0)); - writel(paddr->cr, dev->regs + S5P_CIICRSA(0)); - - cfg &= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS; - writel(cfg, dev->regs + S5P_CIREAL_ISIZE); -} - -void fimc_hw_set_output_addr(struct fimc_dev *dev, - struct fimc_addr *paddr, int index) -{ - int i = (index == -1) ? 0 : index; - do { - writel(paddr->y, dev->regs + S5P_CIOYSA(i)); - writel(paddr->cb, dev->regs + S5P_CIOCBSA(i)); - writel(paddr->cr, dev->regs + S5P_CIOCRSA(i)); - dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X", - i, paddr->y, paddr->cb, paddr->cr); - } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS); -} - -int fimc_hw_set_camera_polarity(struct fimc_dev *fimc, - struct s5p_fimc_isp_info *cam) -{ - u32 cfg = readl(fimc->regs + S5P_CIGCTRL); - - cfg &= ~(S5P_CIGCTRL_INVPOLPCLK | S5P_CIGCTRL_INVPOLVSYNC | - S5P_CIGCTRL_INVPOLHREF | S5P_CIGCTRL_INVPOLHSYNC | - S5P_CIGCTRL_INVPOLFIELD); - - if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) - cfg |= S5P_CIGCTRL_INVPOLPCLK; - - if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) - cfg |= S5P_CIGCTRL_INVPOLVSYNC; - - if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) - cfg |= S5P_CIGCTRL_INVPOLHREF; - - if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) - cfg |= S5P_CIGCTRL_INVPOLHSYNC; - - if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW) - cfg |= S5P_CIGCTRL_INVPOLFIELD; - - writel(cfg, fimc->regs + S5P_CIGCTRL); - - return 0; -} - -int fimc_hw_set_camera_source(struct fimc_dev *fimc, - struct s5p_fimc_isp_info *cam) -{ - struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; - u32 cfg = 0; - u32 bus_width; - int i; - - static const struct { - u32 pixelcode; - u32 cisrcfmt; - u16 bus_width; - } pix_desc[] = { - { V4L2_MBUS_FMT_YUYV8_2X8, S5P_CISRCFMT_ORDER422_YCBYCR, 8 }, - { V4L2_MBUS_FMT_YVYU8_2X8, S5P_CISRCFMT_ORDER422_YCRYCB, 8 }, - { V4L2_MBUS_FMT_VYUY8_2X8, S5P_CISRCFMT_ORDER422_CRYCBY, 8 }, - { V4L2_MBUS_FMT_UYVY8_2X8, S5P_CISRCFMT_ORDER422_CBYCRY, 8 }, - /* TODO: Add pixel codes for 16-bit bus width */ - }; - - if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) { - for (i = 0; i < ARRAY_SIZE(pix_desc); i++) { - if (fimc->vid_cap.mf.code == pix_desc[i].pixelcode) { - cfg = pix_desc[i].cisrcfmt; - bus_width = pix_desc[i].bus_width; - break; - } - } - - if (i == ARRAY_SIZE(pix_desc)) { - v4l2_err(fimc->vid_cap.vfd, - "Camera color format not supported: %d\n", - fimc->vid_cap.mf.code); - return -EINVAL; - } - - if (cam->bus_type == FIMC_ITU_601) { - if (bus_width == 8) - cfg |= S5P_CISRCFMT_ITU601_8BIT; - else if (bus_width == 16) - cfg |= S5P_CISRCFMT_ITU601_16BIT; - } /* else defaults to ITU-R BT.656 8-bit */ - } else if (cam->bus_type == FIMC_MIPI_CSI2) { - if (fimc_fmt_is_jpeg(f->fmt->color)) - cfg |= S5P_CISRCFMT_ITU601_8BIT; - } - - cfg |= S5P_CISRCFMT_HSIZE(f->o_width) | S5P_CISRCFMT_VSIZE(f->o_height); - writel(cfg, fimc->regs + S5P_CISRCFMT); - return 0; -} - - -int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f) -{ - u32 hoff2, voff2; - - u32 cfg = readl(fimc->regs + S5P_CIWDOFST); - - cfg &= ~(S5P_CIWDOFST_HOROFF_MASK | S5P_CIWDOFST_VEROFF_MASK); - cfg |= S5P_CIWDOFST_OFF_EN | - S5P_CIWDOFST_HOROFF(f->offs_h) | - S5P_CIWDOFST_VEROFF(f->offs_v); - - writel(cfg, fimc->regs + S5P_CIWDOFST); - - /* See CIWDOFSTn register description in the datasheet for details. */ - hoff2 = f->o_width - f->width - f->offs_h; - voff2 = f->o_height - f->height - f->offs_v; - cfg = S5P_CIWDOFST2_HOROFF(hoff2) | S5P_CIWDOFST2_VEROFF(voff2); - - writel(cfg, fimc->regs + S5P_CIWDOFST2); - return 0; -} - -int fimc_hw_set_camera_type(struct fimc_dev *fimc, - struct s5p_fimc_isp_info *cam) -{ - u32 cfg, tmp; - struct fimc_vid_cap *vid_cap = &fimc->vid_cap; - - cfg = readl(fimc->regs + S5P_CIGCTRL); - - /* Select ITU B interface, disable Writeback path and test pattern. */ - cfg &= ~(S5P_CIGCTRL_TESTPAT_MASK | S5P_CIGCTRL_SELCAM_ITU_A | - S5P_CIGCTRL_SELCAM_MIPI | S5P_CIGCTRL_CAMIF_SELWB | - S5P_CIGCTRL_SELCAM_MIPI_A | S5P_CIGCTRL_CAM_JPEG); - - if (cam->bus_type == FIMC_MIPI_CSI2) { - cfg |= S5P_CIGCTRL_SELCAM_MIPI; - - if (cam->mux_id == 0) - cfg |= S5P_CIGCTRL_SELCAM_MIPI_A; - - /* TODO: add remaining supported formats. */ - switch (vid_cap->mf.code) { - case V4L2_MBUS_FMT_VYUY8_2X8: - tmp = S5P_CSIIMGFMT_YCBCR422_8BIT; - break; - case V4L2_MBUS_FMT_JPEG_1X8: - tmp = S5P_CSIIMGFMT_USER(1); - cfg |= S5P_CIGCTRL_CAM_JPEG; - break; - default: - v4l2_err(fimc->vid_cap.vfd, - "Not supported camera pixel format: %d", - vid_cap->mf.code); - return -EINVAL; - } - tmp |= (cam->csi_data_align == 32) << 8; - - writel(tmp, fimc->regs + S5P_CSIIMGFMT); - - } else if (cam->bus_type == FIMC_ITU_601 || - cam->bus_type == FIMC_ITU_656) { - if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */ - cfg |= S5P_CIGCTRL_SELCAM_ITU_A; - } else if (cam->bus_type == FIMC_LCD_WB) { - cfg |= S5P_CIGCTRL_CAMIF_SELWB; - } else { - err("invalid camera bus type selected\n"); - return -EINVAL; - } - writel(cfg, fimc->regs + S5P_CIGCTRL); - - return 0; -} diff --git a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/mipi-csis.c b/ANDROID_3.4.5/drivers/media/video/s5p-fimc/mipi-csis.c deleted file mode 100644 index f44f6903..00000000 --- a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/mipi-csis.c +++ /dev/null @@ -1,729 +0,0 @@ -/* - * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver - * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki, <s.nawrocki@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/kernel.h> -#include <linux/memory.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/regulator/consumer.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/videodev2.h> -#include <media/v4l2-subdev.h> -#include <plat/mipi_csis.h> -#include "mipi-csis.h" - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Debug level (0-1)"); - -/* Register map definition */ - -/* CSIS global control */ -#define S5PCSIS_CTRL 0x00 -#define S5PCSIS_CTRL_DPDN_DEFAULT (0 << 31) -#define S5PCSIS_CTRL_DPDN_SWAP (1 << 31) -#define S5PCSIS_CTRL_ALIGN_32BIT (1 << 20) -#define S5PCSIS_CTRL_UPDATE_SHADOW (1 << 16) -#define S5PCSIS_CTRL_WCLK_EXTCLK (1 << 8) -#define S5PCSIS_CTRL_RESET (1 << 4) -#define S5PCSIS_CTRL_ENABLE (1 << 0) - -/* D-PHY control */ -#define S5PCSIS_DPHYCTRL 0x04 -#define S5PCSIS_DPHYCTRL_HSS_MASK (0x1f << 27) -#define S5PCSIS_DPHYCTRL_ENABLE (0x1f << 0) - -#define S5PCSIS_CONFIG 0x08 -#define S5PCSIS_CFG_FMT_YCBCR422_8BIT (0x1e << 2) -#define S5PCSIS_CFG_FMT_RAW8 (0x2a << 2) -#define S5PCSIS_CFG_FMT_RAW10 (0x2b << 2) -#define S5PCSIS_CFG_FMT_RAW12 (0x2c << 2) -/* User defined formats, x = 1...4 */ -#define S5PCSIS_CFG_FMT_USER(x) ((0x30 + x - 1) << 2) -#define S5PCSIS_CFG_FMT_MASK (0x3f << 2) -#define S5PCSIS_CFG_NR_LANE_MASK 3 - -/* Interrupt mask. */ -#define S5PCSIS_INTMSK 0x10 -#define S5PCSIS_INTMSK_EN_ALL 0xf000003f -#define S5PCSIS_INTSRC 0x14 - -/* Pixel resolution */ -#define S5PCSIS_RESOL 0x2c -#define CSIS_MAX_PIX_WIDTH 0xffff -#define CSIS_MAX_PIX_HEIGHT 0xffff - -enum { - CSIS_CLK_MUX, - CSIS_CLK_GATE, -}; - -static char *csi_clock_name[] = { - [CSIS_CLK_MUX] = "sclk_csis", - [CSIS_CLK_GATE] = "csis", -}; -#define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name) - -static const char * const csis_supply_name[] = { - "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */ - "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */ -}; -#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name) - -enum { - ST_POWERED = 1, - ST_STREAMING = 2, - ST_SUSPENDED = 4, -}; - -/** - * struct csis_state - the driver's internal state data structure - * @lock: mutex serializing the subdev and power management operations, - * protecting @format and @flags members - * @pads: CSIS pads array - * @sd: v4l2_subdev associated with CSIS device instance - * @pdev: CSIS platform device - * @regs: mmaped I/O registers memory - * @clock: CSIS clocks - * @irq: requested s5p-mipi-csis irq number - * @flags: the state variable for power and streaming control - * @csis_fmt: current CSIS pixel format - * @format: common media bus format for the source and sink pad - */ -struct csis_state { - struct mutex lock; - struct media_pad pads[CSIS_PADS_NUM]; - struct v4l2_subdev sd; - struct platform_device *pdev; - void __iomem *regs; - struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; - struct clk *clock[NUM_CSIS_CLOCKS]; - int irq; - u32 flags; - const struct csis_pix_format *csis_fmt; - struct v4l2_mbus_framefmt format; -}; - -/** - * struct csis_pix_format - CSIS pixel format description - * @pix_width_alignment: horizontal pixel alignment, width will be - * multiple of 2^pix_width_alignment - * @code: corresponding media bus code - * @fmt_reg: S5PCSIS_CONFIG register value - */ -struct csis_pix_format { - unsigned int pix_width_alignment; - enum v4l2_mbus_pixelcode code; - u32 fmt_reg; -}; - -static const struct csis_pix_format s5pcsis_formats[] = { - { - .code = V4L2_MBUS_FMT_VYUY8_2X8, - .fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT, - }, { - .code = V4L2_MBUS_FMT_JPEG_1X8, - .fmt_reg = S5PCSIS_CFG_FMT_USER(1), - }, -}; - -#define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r) -#define s5pcsis_read(__csis, __r) readl(__csis->regs + __r) - -static struct csis_state *sd_to_csis_state(struct v4l2_subdev *sdev) -{ - return container_of(sdev, struct csis_state, sd); -} - -static const struct csis_pix_format *find_csis_format( - struct v4l2_mbus_framefmt *mf) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(s5pcsis_formats); i++) - if (mf->code == s5pcsis_formats[i].code) - return &s5pcsis_formats[i]; - return NULL; -} - -static void s5pcsis_enable_interrupts(struct csis_state *state, bool on) -{ - u32 val = s5pcsis_read(state, S5PCSIS_INTMSK); - - val = on ? val | S5PCSIS_INTMSK_EN_ALL : - val & ~S5PCSIS_INTMSK_EN_ALL; - s5pcsis_write(state, S5PCSIS_INTMSK, val); -} - -static void s5pcsis_reset(struct csis_state *state) -{ - u32 val = s5pcsis_read(state, S5PCSIS_CTRL); - - s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_RESET); - udelay(10); -} - -static void s5pcsis_system_enable(struct csis_state *state, int on) -{ - u32 val; - - val = s5pcsis_read(state, S5PCSIS_CTRL); - if (on) - val |= S5PCSIS_CTRL_ENABLE; - else - val &= ~S5PCSIS_CTRL_ENABLE; - s5pcsis_write(state, S5PCSIS_CTRL, val); - - val = s5pcsis_read(state, S5PCSIS_DPHYCTRL); - if (on) - val |= S5PCSIS_DPHYCTRL_ENABLE; - else - val &= ~S5PCSIS_DPHYCTRL_ENABLE; - s5pcsis_write(state, S5PCSIS_DPHYCTRL, val); -} - -/* Called with the state.lock mutex held */ -static void __s5pcsis_set_format(struct csis_state *state) -{ - struct v4l2_mbus_framefmt *mf = &state->format; - u32 val; - - v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n", - mf->code, mf->width, mf->height); - - /* Color format */ - val = s5pcsis_read(state, S5PCSIS_CONFIG); - val = (val & ~S5PCSIS_CFG_FMT_MASK) | state->csis_fmt->fmt_reg; - s5pcsis_write(state, S5PCSIS_CONFIG, val); - - /* Pixel resolution */ - val = (mf->width << 16) | mf->height; - s5pcsis_write(state, S5PCSIS_RESOL, val); -} - -static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle) -{ - u32 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL); - - val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (settle << 27); - s5pcsis_write(state, S5PCSIS_DPHYCTRL, val); -} - -static void s5pcsis_set_params(struct csis_state *state) -{ - struct s5p_platform_mipi_csis *pdata = state->pdev->dev.platform_data; - u32 val; - - val = s5pcsis_read(state, S5PCSIS_CONFIG); - val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (pdata->lanes - 1); - s5pcsis_write(state, S5PCSIS_CONFIG, val); - - __s5pcsis_set_format(state); - s5pcsis_set_hsync_settle(state, pdata->hs_settle); - - val = s5pcsis_read(state, S5PCSIS_CTRL); - if (pdata->alignment == 32) - val |= S5PCSIS_CTRL_ALIGN_32BIT; - else /* 24-bits */ - val &= ~S5PCSIS_CTRL_ALIGN_32BIT; - /* Not using external clock. */ - val &= ~S5PCSIS_CTRL_WCLK_EXTCLK; - s5pcsis_write(state, S5PCSIS_CTRL, val); - - /* Update the shadow register. */ - val = s5pcsis_read(state, S5PCSIS_CTRL); - s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_UPDATE_SHADOW); -} - -static void s5pcsis_clk_put(struct csis_state *state) -{ - int i; - - for (i = 0; i < NUM_CSIS_CLOCKS; i++) { - if (IS_ERR_OR_NULL(state->clock[i])) - continue; - clk_unprepare(state->clock[i]); - clk_put(state->clock[i]); - state->clock[i] = NULL; - } -} - -static int s5pcsis_clk_get(struct csis_state *state) -{ - struct device *dev = &state->pdev->dev; - int i, ret; - - for (i = 0; i < NUM_CSIS_CLOCKS; i++) { - state->clock[i] = clk_get(dev, csi_clock_name[i]); - if (IS_ERR(state->clock[i])) - goto err; - ret = clk_prepare(state->clock[i]); - if (ret < 0) { - clk_put(state->clock[i]); - state->clock[i] = NULL; - goto err; - } - } - return 0; -err: - s5pcsis_clk_put(state); - dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]); - return -ENXIO; -} - -static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) -{ - struct csis_state *state = sd_to_csis_state(sd); - struct device *dev = &state->pdev->dev; - - if (on) - return pm_runtime_get_sync(dev); - - return pm_runtime_put_sync(dev); -} - -static void s5pcsis_start_stream(struct csis_state *state) -{ - s5pcsis_reset(state); - s5pcsis_set_params(state); - s5pcsis_system_enable(state, true); - s5pcsis_enable_interrupts(state, true); -} - -static void s5pcsis_stop_stream(struct csis_state *state) -{ - s5pcsis_enable_interrupts(state, false); - s5pcsis_system_enable(state, false); -} - -/* v4l2_subdev operations */ -static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable) -{ - struct csis_state *state = sd_to_csis_state(sd); - int ret = 0; - - v4l2_dbg(1, debug, sd, "%s: %d, state: 0x%x\n", - __func__, enable, state->flags); - - if (enable) { - ret = pm_runtime_get_sync(&state->pdev->dev); - if (ret && ret != 1) - return ret; - } - mutex_lock(&state->lock); - if (enable) { - if (state->flags & ST_SUSPENDED) { - ret = -EBUSY; - goto unlock; - } - s5pcsis_start_stream(state); - state->flags |= ST_STREAMING; - } else { - s5pcsis_stop_stream(state); - state->flags &= ~ST_STREAMING; - } -unlock: - mutex_unlock(&state->lock); - if (!enable) - pm_runtime_put(&state->pdev->dev); - - return ret == 1 ? 0 : ret; -} - -static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_mbus_code_enum *code) -{ - if (code->index >= ARRAY_SIZE(s5pcsis_formats)) - return -EINVAL; - - code->code = s5pcsis_formats[code->index].code; - return 0; -} - -static struct csis_pix_format const *s5pcsis_try_format( - struct v4l2_mbus_framefmt *mf) -{ - struct csis_pix_format const *csis_fmt; - - csis_fmt = find_csis_format(mf); - if (csis_fmt == NULL) - csis_fmt = &s5pcsis_formats[0]; - - mf->code = csis_fmt->code; - v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH, - csis_fmt->pix_width_alignment, - &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1, - 0); - return csis_fmt; -} - -static struct v4l2_mbus_framefmt *__s5pcsis_get_format( - struct csis_state *state, struct v4l2_subdev_fh *fh, - u32 pad, enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL; - - return &state->format; -} - -static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, - struct v4l2_subdev_format *fmt) -{ - struct csis_state *state = sd_to_csis_state(sd); - struct csis_pix_format const *csis_fmt; - struct v4l2_mbus_framefmt *mf; - - if (fmt->pad != CSIS_PAD_SOURCE && fmt->pad != CSIS_PAD_SINK) - return -EINVAL; - - mf = __s5pcsis_get_format(state, fh, fmt->pad, fmt->which); - - if (fmt->pad == CSIS_PAD_SOURCE) { - if (mf) { - mutex_lock(&state->lock); - fmt->format = *mf; - mutex_unlock(&state->lock); - } - return 0; - } - csis_fmt = s5pcsis_try_format(&fmt->format); - if (mf) { - mutex_lock(&state->lock); - *mf = fmt->format; - if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) - state->csis_fmt = csis_fmt; - mutex_unlock(&state->lock); - } - return 0; -} - -static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, - struct v4l2_subdev_format *fmt) -{ - struct csis_state *state = sd_to_csis_state(sd); - struct v4l2_mbus_framefmt *mf; - - if (fmt->pad != CSIS_PAD_SOURCE && fmt->pad != CSIS_PAD_SINK) - return -EINVAL; - - mf = __s5pcsis_get_format(state, fh, fmt->pad, fmt->which); - if (!mf) - return -EINVAL; - - mutex_lock(&state->lock); - fmt->format = *mf; - mutex_unlock(&state->lock); - return 0; -} - -static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0); - - format->colorspace = V4L2_COLORSPACE_JPEG; - format->code = s5pcsis_formats[0].code; - format->width = S5PCSIS_DEF_PIX_WIDTH; - format->height = S5PCSIS_DEF_PIX_HEIGHT; - format->field = V4L2_FIELD_NONE; - - return 0; -} - -static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = { - .open = s5pcsis_open, -}; - -static struct v4l2_subdev_core_ops s5pcsis_core_ops = { - .s_power = s5pcsis_s_power, -}; - -static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = { - .enum_mbus_code = s5pcsis_enum_mbus_code, - .get_fmt = s5pcsis_get_fmt, - .set_fmt = s5pcsis_set_fmt, -}; - -static struct v4l2_subdev_video_ops s5pcsis_video_ops = { - .s_stream = s5pcsis_s_stream, -}; - -static struct v4l2_subdev_ops s5pcsis_subdev_ops = { - .core = &s5pcsis_core_ops, - .pad = &s5pcsis_pad_ops, - .video = &s5pcsis_video_ops, -}; - -static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id) -{ - struct csis_state *state = dev_id; - u32 val; - - /* Just clear the interrupt pending bits. */ - val = s5pcsis_read(state, S5PCSIS_INTSRC); - s5pcsis_write(state, S5PCSIS_INTSRC, val); - - return IRQ_HANDLED; -} - -static int __devinit s5pcsis_probe(struct platform_device *pdev) -{ - struct s5p_platform_mipi_csis *pdata; - struct resource *mem_res; - struct csis_state *state; - int ret = -ENOMEM; - int i; - - state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; - - mutex_init(&state->lock); - state->pdev = pdev; - - pdata = pdev->dev.platform_data; - if (pdata == NULL || pdata->phy_enable == NULL) { - dev_err(&pdev->dev, "Platform data not fully specified\n"); - return -EINVAL; - } - - if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) || - pdata->lanes > CSIS0_MAX_LANES) { - dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", - pdata->lanes); - return -EINVAL; - } - - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - state->regs = devm_request_and_ioremap(&pdev->dev, mem_res); - if (state->regs == NULL) { - dev_err(&pdev->dev, "Failed to request and remap io memory\n"); - return -ENXIO; - } - - state->irq = platform_get_irq(pdev, 0); - if (state->irq < 0) { - dev_err(&pdev->dev, "Failed to get irq\n"); - return state->irq; - } - - for (i = 0; i < CSIS_NUM_SUPPLIES; i++) - state->supplies[i].supply = csis_supply_name[i]; - - ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, - state->supplies); - if (ret) - return ret; - - ret = s5pcsis_clk_get(state); - if (ret) - goto e_clkput; - - clk_enable(state->clock[CSIS_CLK_MUX]); - if (pdata->clk_rate) - clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); - else - dev_WARN(&pdev->dev, "No clock frequency specified!\n"); - - ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler, - 0, dev_name(&pdev->dev), state); - if (ret) { - dev_err(&pdev->dev, "Interrupt request failed\n"); - goto e_regput; - } - - v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops); - state->sd.owner = THIS_MODULE; - strlcpy(state->sd.name, dev_name(&pdev->dev), sizeof(state->sd.name)); - state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - state->csis_fmt = &s5pcsis_formats[0]; - - state->format.code = s5pcsis_formats[0].code; - state->format.width = S5PCSIS_DEF_PIX_WIDTH; - state->format.height = S5PCSIS_DEF_PIX_HEIGHT; - - state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - ret = media_entity_init(&state->sd.entity, - CSIS_PADS_NUM, state->pads, 0); - if (ret < 0) - goto e_clkput; - - /* This allows to retrieve the platform device id by the host driver */ - v4l2_set_subdevdata(&state->sd, pdev); - - /* .. and a pointer to the subdev. */ - platform_set_drvdata(pdev, &state->sd); - - pm_runtime_enable(&pdev->dev); - return 0; - -e_regput: - regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); -e_clkput: - clk_disable(state->clock[CSIS_CLK_MUX]); - s5pcsis_clk_put(state); - return ret; -} - -static int s5pcsis_pm_suspend(struct device *dev, bool runtime) -{ - struct s5p_platform_mipi_csis *pdata = dev->platform_data; - struct platform_device *pdev = to_platform_device(dev); - struct v4l2_subdev *sd = platform_get_drvdata(pdev); - struct csis_state *state = sd_to_csis_state(sd); - int ret = 0; - - v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n", - __func__, state->flags); - - mutex_lock(&state->lock); - if (state->flags & ST_POWERED) { - s5pcsis_stop_stream(state); - ret = pdata->phy_enable(state->pdev, false); - if (ret) - goto unlock; - ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES, - state->supplies); - if (ret) - goto unlock; - clk_disable(state->clock[CSIS_CLK_GATE]); - state->flags &= ~ST_POWERED; - if (!runtime) - state->flags |= ST_SUSPENDED; - } - unlock: - mutex_unlock(&state->lock); - return ret ? -EAGAIN : 0; -} - -static int s5pcsis_pm_resume(struct device *dev, bool runtime) -{ - struct s5p_platform_mipi_csis *pdata = dev->platform_data; - struct platform_device *pdev = to_platform_device(dev); - struct v4l2_subdev *sd = platform_get_drvdata(pdev); - struct csis_state *state = sd_to_csis_state(sd); - int ret = 0; - - v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n", - __func__, state->flags); - - mutex_lock(&state->lock); - if (!runtime && !(state->flags & ST_SUSPENDED)) - goto unlock; - - if (!(state->flags & ST_POWERED)) { - ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES, - state->supplies); - if (ret) - goto unlock; - ret = pdata->phy_enable(state->pdev, true); - if (!ret) { - state->flags |= ST_POWERED; - } else { - regulator_bulk_disable(CSIS_NUM_SUPPLIES, - state->supplies); - goto unlock; - } - clk_enable(state->clock[CSIS_CLK_GATE]); - } - if (state->flags & ST_STREAMING) - s5pcsis_start_stream(state); - - state->flags &= ~ST_SUSPENDED; - unlock: - mutex_unlock(&state->lock); - return ret ? -EAGAIN : 0; -} - -#ifdef CONFIG_PM_SLEEP -static int s5pcsis_suspend(struct device *dev) -{ - return s5pcsis_pm_suspend(dev, false); -} - -static int s5pcsis_resume(struct device *dev) -{ - return s5pcsis_pm_resume(dev, false); -} -#endif - -#ifdef CONFIG_PM_RUNTIME -static int s5pcsis_runtime_suspend(struct device *dev) -{ - return s5pcsis_pm_suspend(dev, true); -} - -static int s5pcsis_runtime_resume(struct device *dev) -{ - return s5pcsis_pm_resume(dev, true); -} -#endif - -static int __devexit s5pcsis_remove(struct platform_device *pdev) -{ - struct v4l2_subdev *sd = platform_get_drvdata(pdev); - struct csis_state *state = sd_to_csis_state(sd); - - pm_runtime_disable(&pdev->dev); - s5pcsis_pm_suspend(&pdev->dev, false); - clk_disable(state->clock[CSIS_CLK_MUX]); - pm_runtime_set_suspended(&pdev->dev); - s5pcsis_clk_put(state); - regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); - - media_entity_cleanup(&state->sd.entity); - - return 0; -} - -static const struct dev_pm_ops s5pcsis_pm_ops = { - SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume) -}; - -static struct platform_driver s5pcsis_driver = { - .probe = s5pcsis_probe, - .remove = __devexit_p(s5pcsis_remove), - .driver = { - .name = CSIS_DRIVER_NAME, - .owner = THIS_MODULE, - .pm = &s5pcsis_pm_ops, - }, -}; - -static int __init s5pcsis_init(void) -{ - return platform_driver_probe(&s5pcsis_driver, s5pcsis_probe); -} - -static void __exit s5pcsis_exit(void) -{ - platform_driver_unregister(&s5pcsis_driver); -} - -module_init(s5pcsis_init); -module_exit(s5pcsis_exit); - -MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); -MODULE_DESCRIPTION("S5P/EXYNOS4 MIPI CSI receiver driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/mipi-csis.h b/ANDROID_3.4.5/drivers/media/video/s5p-fimc/mipi-csis.h deleted file mode 100644 index 27092863..00000000 --- a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/mipi-csis.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef S5P_MIPI_CSIS_H_ -#define S5P_MIPI_CSIS_H_ - -#define CSIS_DRIVER_NAME "s5p-mipi-csis" -#define CSIS_MAX_ENTITIES 2 -#define CSIS0_MAX_LANES 4 -#define CSIS1_MAX_LANES 2 - -#define CSIS_PAD_SINK 0 -#define CSIS_PAD_SOURCE 1 -#define CSIS_PADS_NUM 2 - -#define S5PCSIS_DEF_PIX_WIDTH 640 -#define S5PCSIS_DEF_PIX_HEIGHT 480 - -#endif diff --git a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/regs-fimc.h b/ANDROID_3.4.5/drivers/media/video/s5p-fimc/regs-fimc.h deleted file mode 100644 index c7a5bc51..00000000 --- a/ANDROID_3.4.5/drivers/media/video/s5p-fimc/regs-fimc.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Register definition file for Samsung Camera Interface (FIMC) driver - * - * Copyright (c) 2010 Samsung Electronics - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef REGS_FIMC_H_ -#define REGS_FIMC_H_ - -/* Input source format */ -#define S5P_CISRCFMT 0x00 -#define S5P_CISRCFMT_ITU601_8BIT (1 << 31) -#define S5P_CISRCFMT_ITU601_16BIT (1 << 29) -#define S5P_CISRCFMT_ORDER422_YCBYCR (0 << 14) -#define S5P_CISRCFMT_ORDER422_YCRYCB (1 << 14) -#define S5P_CISRCFMT_ORDER422_CBYCRY (2 << 14) -#define S5P_CISRCFMT_ORDER422_CRYCBY (3 << 14) -#define S5P_CISRCFMT_HSIZE(x) ((x) << 16) -#define S5P_CISRCFMT_VSIZE(x) ((x) << 0) - -/* Window offset */ -#define S5P_CIWDOFST 0x04 -#define S5P_CIWDOFST_OFF_EN (1 << 31) -#define S5P_CIWDOFST_CLROVFIY (1 << 30) -#define S5P_CIWDOFST_CLROVRLB (1 << 29) -#define S5P_CIWDOFST_HOROFF_MASK (0x7ff << 16) -#define S5P_CIWDOFST_CLROVFICB (1 << 15) -#define S5P_CIWDOFST_CLROVFICR (1 << 14) -#define S5P_CIWDOFST_HOROFF(x) ((x) << 16) -#define S5P_CIWDOFST_VEROFF(x) ((x) << 0) -#define S5P_CIWDOFST_VEROFF_MASK (0xfff << 0) - -/* Global control */ -#define S5P_CIGCTRL 0x08 -#define S5P_CIGCTRL_SWRST (1 << 31) -#define S5P_CIGCTRL_CAMRST_A (1 << 30) -#define S5P_CIGCTRL_SELCAM_ITU_A (1 << 29) -#define S5P_CIGCTRL_TESTPAT_NORMAL (0 << 27) -#define S5P_CIGCTRL_TESTPAT_COLOR_BAR (1 << 27) -#define S5P_CIGCTRL_TESTPAT_HOR_INC (2 << 27) -#define S5P_CIGCTRL_TESTPAT_VER_INC (3 << 27) -#define S5P_CIGCTRL_TESTPAT_MASK (3 << 27) -#define S5P_CIGCTRL_TESTPAT_SHIFT (27) -#define S5P_CIGCTRL_INVPOLPCLK (1 << 26) -#define S5P_CIGCTRL_INVPOLVSYNC (1 << 25) -#define S5P_CIGCTRL_INVPOLHREF (1 << 24) -#define S5P_CIGCTRL_IRQ_OVFEN (1 << 22) -#define S5P_CIGCTRL_HREF_MASK (1 << 21) -#define S5P_CIGCTRL_IRQ_LEVEL (1 << 20) -#define S5P_CIGCTRL_IRQ_CLR (1 << 19) -#define S5P_CIGCTRL_IRQ_ENABLE (1 << 16) -#define S5P_CIGCTRL_SHDW_DISABLE (1 << 12) -#define S5P_CIGCTRL_CAM_JPEG (1 << 8) -#define S5P_CIGCTRL_SELCAM_MIPI_A (1 << 7) -#define S5P_CIGCTRL_CAMIF_SELWB (1 << 6) -/* 0 - ITU601; 1 - ITU709 */ -#define S5P_CIGCTRL_CSC_ITU601_709 (1 << 5) -#define S5P_CIGCTRL_INVPOLHSYNC (1 << 4) -#define S5P_CIGCTRL_SELCAM_MIPI (1 << 3) -#define S5P_CIGCTRL_INVPOLFIELD (1 << 1) -#define S5P_CIGCTRL_INTERLACE (1 << 0) - -/* Window offset 2 */ -#define S5P_CIWDOFST2 0x14 -#define S5P_CIWDOFST2_HOROFF_MASK (0xfff << 16) -#define S5P_CIWDOFST2_VEROFF_MASK (0xfff << 0) -#define S5P_CIWDOFST2_HOROFF(x) ((x) << 16) -#define S5P_CIWDOFST2_VEROFF(x) ((x) << 0) - -/* Output DMA Y/Cb/Cr plane start addresses */ -#define S5P_CIOYSA(n) (0x18 + (n) * 4) -#define S5P_CIOCBSA(n) (0x28 + (n) * 4) -#define S5P_CIOCRSA(n) (0x38 + (n) * 4) - -/* Target image format */ -#define S5P_CITRGFMT 0x48 -#define S5P_CITRGFMT_INROT90 (1 << 31) -#define S5P_CITRGFMT_YCBCR420 (0 << 29) -#define S5P_CITRGFMT_YCBCR422 (1 << 29) -#define S5P_CITRGFMT_YCBCR422_1P (2 << 29) -#define S5P_CITRGFMT_RGB (3 << 29) -#define S5P_CITRGFMT_FMT_MASK (3 << 29) -#define S5P_CITRGFMT_HSIZE_MASK (0xfff << 16) -#define S5P_CITRGFMT_FLIP_SHIFT (14) -#define S5P_CITRGFMT_FLIP_NORMAL (0 << 14) -#define S5P_CITRGFMT_FLIP_X_MIRROR (1 << 14) -#define S5P_CITRGFMT_FLIP_Y_MIRROR (2 << 14) -#define S5P_CITRGFMT_FLIP_180 (3 << 14) -#define S5P_CITRGFMT_FLIP_MASK (3 << 14) -#define S5P_CITRGFMT_OUTROT90 (1 << 13) -#define S5P_CITRGFMT_VSIZE_MASK (0xfff << 0) -#define S5P_CITRGFMT_HSIZE(x) ((x) << 16) -#define S5P_CITRGFMT_VSIZE(x) ((x) << 0) - -/* Output DMA control */ -#define S5P_CIOCTRL 0x4c -#define S5P_CIOCTRL_ORDER422_MASK (3 << 0) -#define S5P_CIOCTRL_ORDER422_CRYCBY (0 << 0) -#define S5P_CIOCTRL_ORDER422_CBYCRY (1 << 0) -#define S5P_CIOCTRL_ORDER422_YCRYCB (2 << 0) -#define S5P_CIOCTRL_ORDER422_YCBYCR (3 << 0) -#define S5P_CIOCTRL_LASTIRQ_ENABLE (1 << 2) -#define S5P_CIOCTRL_YCBCR_3PLANE (0 << 3) -#define S5P_CIOCTRL_YCBCR_2PLANE (1 << 3) -#define S5P_CIOCTRL_YCBCR_PLANE_MASK (1 << 3) -#define S5P_CIOCTRL_ALPHA_OUT_MASK (0xff << 4) -#define S5P_CIOCTRL_RGB16FMT_MASK (3 << 16) -#define S5P_CIOCTRL_RGB565 (0 << 16) -#define S5P_CIOCTRL_ARGB1555 (1 << 16) -#define S5P_CIOCTRL_ARGB4444 (2 << 16) -#define S5P_CIOCTRL_ORDER2P_SHIFT (24) -#define S5P_CIOCTRL_ORDER2P_MASK (3 << 24) -#define S5P_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24) - -/* Pre-scaler control 1 */ -#define S5P_CISCPRERATIO 0x50 -#define S5P_CISCPRERATIO_SHFACTOR(x) ((x) << 28) -#define S5P_CISCPRERATIO_HOR(x) ((x) << 16) -#define S5P_CISCPRERATIO_VER(x) ((x) << 0) - -#define S5P_CISCPREDST 0x54 -#define S5P_CISCPREDST_WIDTH(x) ((x) << 16) -#define S5P_CISCPREDST_HEIGHT(x) ((x) << 0) - -/* Main scaler control */ -#define S5P_CISCCTRL 0x58 -#define S5P_CISCCTRL_SCALERBYPASS (1 << 31) -#define S5P_CISCCTRL_SCALEUP_H (1 << 30) -#define S5P_CISCCTRL_SCALEUP_V (1 << 29) -#define S5P_CISCCTRL_CSCR2Y_WIDE (1 << 28) -#define S5P_CISCCTRL_CSCY2R_WIDE (1 << 27) -#define S5P_CISCCTRL_LCDPATHEN_FIFO (1 << 26) -#define S5P_CISCCTRL_INTERLACE (1 << 25) -#define S5P_CISCCTRL_SCALERSTART (1 << 15) -#define S5P_CISCCTRL_INRGB_FMT_RGB565 (0 << 13) -#define S5P_CISCCTRL_INRGB_FMT_RGB666 (1 << 13) -#define S5P_CISCCTRL_INRGB_FMT_RGB888 (2 << 13) -#define S5P_CISCCTRL_INRGB_FMT_MASK (3 << 13) -#define S5P_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11) -#define S5P_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11) -#define S5P_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11) -#define S5P_CISCCTRL_OUTRGB_FMT_MASK (3 << 11) -#define S5P_CISCCTRL_RGB_EXT (1 << 10) -#define S5P_CISCCTRL_ONE2ONE (1 << 9) -#define S5P_CISCCTRL_MHRATIO(x) ((x) << 16) -#define S5P_CISCCTRL_MVRATIO(x) ((x) << 0) -#define S5P_CISCCTRL_MHRATIO_MASK (0x1ff << 16) -#define S5P_CISCCTRL_MVRATIO_MASK (0x1ff << 0) -#define S5P_CISCCTRL_MHRATIO_EXT(x) (((x) >> 6) << 16) -#define S5P_CISCCTRL_MVRATIO_EXT(x) (((x) >> 6) << 0) - -/* Target area */ -#define S5P_CITAREA 0x5c -#define S5P_CITAREA_MASK 0x0fffffff - -/* General status */ -#define S5P_CISTATUS 0x64 -#define S5P_CISTATUS_OVFIY (1 << 31) -#define S5P_CISTATUS_OVFICB (1 << 30) -#define S5P_CISTATUS_OVFICR (1 << 29) -#define S5P_CISTATUS_VSYNC (1 << 28) -#define S5P_CISTATUS_FRAMECNT_MASK (3 << 26) -#define S5P_CISTATUS_FRAMECNT_SHIFT 26 -#define S5P_CISTATUS_WINOFF_EN (1 << 25) -#define S5P_CISTATUS_IMGCPT_EN (1 << 22) -#define S5P_CISTATUS_IMGCPT_SCEN (1 << 21) -#define S5P_CISTATUS_VSYNC_A (1 << 20) -#define S5P_CISTATUS_VSYNC_B (1 << 19) -#define S5P_CISTATUS_OVRLB (1 << 18) -#define S5P_CISTATUS_FRAME_END (1 << 17) -#define S5P_CISTATUS_LASTCAPT_END (1 << 16) -#define S5P_CISTATUS_VVALID_A (1 << 15) -#define S5P_CISTATUS_VVALID_B (1 << 14) - -/* Indexes to the last and the currently processed buffer. */ -#define S5P_CISTATUS2 0x68 - -/* Image capture control */ -#define S5P_CIIMGCPT 0xc0 -#define S5P_CIIMGCPT_IMGCPTEN (1 << 31) -#define S5P_CIIMGCPT_IMGCPTEN_SC (1 << 30) -#define S5P_CIIMGCPT_CPT_FREN_ENABLE (1 << 25) -#define S5P_CIIMGCPT_CPT_FRMOD_CNT (1 << 18) - -/* Frame capture sequence */ -#define S5P_CICPTSEQ 0xc4 - -/* Image effect */ -#define S5P_CIIMGEFF 0xd0 -#define S5P_CIIMGEFF_IE_ENABLE (1 << 30) -#define S5P_CIIMGEFF_IE_SC_BEFORE (0 << 29) -#define S5P_CIIMGEFF_IE_SC_AFTER (1 << 29) -#define S5P_CIIMGEFF_FIN_BYPASS (0 << 26) -#define S5P_CIIMGEFF_FIN_ARBITRARY (1 << 26) -#define S5P_CIIMGEFF_FIN_NEGATIVE (2 << 26) -#define S5P_CIIMGEFF_FIN_ARTFREEZE (3 << 26) -#define S5P_CIIMGEFF_FIN_EMBOSSING (4 << 26) -#define S5P_CIIMGEFF_FIN_SILHOUETTE (5 << 26) -#define S5P_CIIMGEFF_FIN_MASK (7 << 26) -#define S5P_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff < 0)) -#define S5P_CIIMGEFF_PAT_CB(x) ((x) << 13) -#define S5P_CIIMGEFF_PAT_CR(x) ((x) << 0) - -/* Input DMA Y/Cb/Cr plane start address 0/1 */ -#define S5P_CIIYSA(n) (0xd4 + (n) * 0x70) -#define S5P_CIICBSA(n) (0xd8 + (n) * 0x70) -#define S5P_CIICRSA(n) (0xdc + (n) * 0x70) - -/* Real input DMA image size */ -#define S5P_CIREAL_ISIZE 0xf8 -#define S5P_CIREAL_ISIZE_AUTOLOAD_EN (1 << 31) -#define S5P_CIREAL_ISIZE_ADDR_CH_DIS (1 << 30) -#define S5P_CIREAL_ISIZE_HEIGHT(x) ((x) << 16) -#define S5P_CIREAL_ISIZE_WIDTH(x) ((x) << 0) - - -/* Input DMA control */ -#define S5P_MSCTRL 0xfc -#define S5P_MSCTRL_IN_BURST_COUNT_MASK (0xF << 24) -#define S5P_MSCTRL_2P_IN_ORDER_MASK (3 << 16) -#define S5P_MSCTRL_2P_IN_ORDER_SHIFT 16 -#define S5P_MSCTRL_C_INT_IN_3PLANE (0 << 15) -#define S5P_MSCTRL_C_INT_IN_2PLANE (1 << 15) -#define S5P_MSCTRL_C_INT_IN_MASK (1 << 15) -#define S5P_MSCTRL_FLIP_SHIFT 13 -#define S5P_MSCTRL_FLIP_MASK (3 << 13) -#define S5P_MSCTRL_FLIP_NORMAL (0 << 13) -#define S5P_MSCTRL_FLIP_X_MIRROR (1 << 13) -#define S5P_MSCTRL_FLIP_Y_MIRROR (2 << 13) -#define S5P_MSCTRL_FLIP_180 (3 << 13) -#define S5P_MSCTRL_FIFO_CTRL_FULL (1 << 12) -#define S5P_MSCTRL_ORDER422_SHIFT 4 -#define S5P_MSCTRL_ORDER422_YCBYCR (0 << 4) -#define S5P_MSCTRL_ORDER422_CBYCRY (1 << 4) -#define S5P_MSCTRL_ORDER422_YCRYCB (2 << 4) -#define S5P_MSCTRL_ORDER422_CRYCBY (3 << 4) -#define S5P_MSCTRL_ORDER422_MASK (3 << 4) -#define S5P_MSCTRL_INPUT_EXTCAM (0 << 3) -#define S5P_MSCTRL_INPUT_MEMORY (1 << 3) -#define S5P_MSCTRL_INPUT_MASK (1 << 3) -#define S5P_MSCTRL_INFORMAT_YCBCR420 (0 << 1) -#define S5P_MSCTRL_INFORMAT_YCBCR422 (1 << 1) -#define S5P_MSCTRL_INFORMAT_YCBCR422_1P (2 << 1) -#define S5P_MSCTRL_INFORMAT_RGB (3 << 1) -#define S5P_MSCTRL_INFORMAT_MASK (3 << 1) -#define S5P_MSCTRL_ENVID (1 << 0) -#define S5P_MSCTRL_IN_BURST_COUNT(x) ((x) << 24) - -/* Output DMA Y/Cb/Cr offset */ -#define S5P_CIOYOFF 0x168 -#define S5P_CIOCBOFF 0x16c -#define S5P_CIOCROFF 0x170 - -/* Input DMA Y/Cb/Cr offset */ -#define S5P_CIIYOFF 0x174 -#define S5P_CIICBOFF 0x178 -#define S5P_CIICROFF 0x17c - -#define S5P_CIO_OFFS_VER(x) ((x) << 16) -#define S5P_CIO_OFFS_HOR(x) ((x) << 0) - -/* Input DMA original image size */ -#define S5P_ORGISIZE 0x180 - -/* Output DMA original image size */ -#define S5P_ORGOSIZE 0x184 - -#define S5P_ORIG_SIZE_VER(x) ((x) << 16) -#define S5P_ORIG_SIZE_HOR(x) ((x) << 0) - -/* Real output DMA image size (extension register) */ -#define S5P_CIEXTEN 0x188 -#define S5P_CIEXTEN_MHRATIO_EXT(x) (((x) & 0x3f) << 10) -#define S5P_CIEXTEN_MVRATIO_EXT(x) ((x) & 0x3f) -#define S5P_CIEXTEN_MHRATIO_EXT_MASK (0x3f << 10) -#define S5P_CIEXTEN_MVRATIO_EXT_MASK 0x3f - -#define S5P_CIDMAPARAM 0x18c -#define S5P_CIDMAPARAM_R_LINEAR (0 << 29) -#define S5P_CIDMAPARAM_R_64X32 (3 << 29) -#define S5P_CIDMAPARAM_W_LINEAR (0 << 13) -#define S5P_CIDMAPARAM_W_64X32 (3 << 13) -#define S5P_CIDMAPARAM_TILE_MASK ((3 << 29) | (3 << 13)) - -/* MIPI CSI image format */ -#define S5P_CSIIMGFMT 0x194 -#define S5P_CSIIMGFMT_YCBCR422_8BIT 0x1e -#define S5P_CSIIMGFMT_RAW8 0x2a -#define S5P_CSIIMGFMT_RAW10 0x2b -#define S5P_CSIIMGFMT_RAW12 0x2c -/* User defined formats. x = 0...16. */ -#define S5P_CSIIMGFMT_USER(x) (0x30 + x - 1) - -/* Output frame buffer sequence mask */ -#define S5P_CIFCNTSEQ 0x1FC - -#endif /* REGS_FIMC_H_ */ |