diff options
author | Mauro Carvalho Chehab <mchehab@kernel.org> | 2022-03-13 11:18:16 +0100 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@kernel.org> | 2022-03-18 05:56:51 +0100 |
commit | 238c84f71120f41c45301359902a912a19370f3d (patch) | |
tree | c16ced196c926c08b0c1e9513a19710bbbfc9bfa /drivers/media/platform/exynos4-is | |
parent | 9b18ef7c9ff408df170ac339c57a759145c055d2 (diff) |
media: platform: rename exynos4-is/ to samsung/exynos4-is/
As the end goal is to have platform drivers split by vendor,
rename exynos4-is/ to samsung/exynos4-is/.
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'drivers/media/platform/exynos4-is')
35 files changed, 0 insertions, 17418 deletions
diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig deleted file mode 100644 index 868bb86c7699..000000000000 --- a/drivers/media/platform/exynos4-is/Kconfig +++ /dev/null @@ -1,84 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -config VIDEO_SAMSUNG_EXYNOS4_IS - tristate "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver" - depends on V4L_PLATFORM_DRIVERS - depends on VIDEO_V4L2 && OF && COMMON_CLK - depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST - select MEDIA_CONTROLLER - select VIDEO_V4L2_SUBDEV_API - select V4L2_FWNODE - help - Say Y here to enable camera host interface devices for - Samsung S5P and EXYNOS SoC series. - -if VIDEO_SAMSUNG_EXYNOS4_IS - -config VIDEO_EXYNOS4_IS_COMMON - tristate - -config VIDEO_S5P_FIMC - tristate "S5P/EXYNOS4 FIMC/CAMIF camera interface driver" - depends on I2C - depends on HAS_DMA - select VIDEOBUF2_DMA_CONTIG - select V4L2_MEM2MEM_DEV - select MFD_SYSCON - select VIDEO_EXYNOS4_IS_COMMON - help - This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC camera host - interface and video postprocessor (FIMC) devices. - - To compile this driver as a module, choose M here: the - module will be called s5p-fimc. - -config VIDEO_S5P_MIPI_CSIS - tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver" - depends on REGULATOR - select GENERIC_PHY - select V4L2_FWNODE - help - This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2 - receiver (MIPI-CSIS) devices. - - To compile this driver as a module, choose M here: the - module will be called s5p-csis. - -config VIDEO_EXYNOS_FIMC_LITE - tristate "EXYNOS FIMC-LITE camera interface driver" - depends on I2C - depends on SOC_EXYNOS4412 || SOC_EXYNOS5250 || COMPILE_TEST - depends on HAS_DMA - select VIDEOBUF2_DMA_CONTIG - select VIDEO_EXYNOS4_IS_COMMON - help - This is a V4L2 driver for Samsung EXYNOS4/5 SoC FIMC-LITE camera - host interface. - - To compile this driver as a module, choose M here: the - module will be called exynos-fimc-lite. - -config VIDEO_EXYNOS4_FIMC_IS - tristate "EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver" - depends on I2C - depends on HAS_DMA - select VIDEOBUF2_DMA_CONTIG - depends on OF - select FW_LOADER - help - This is a V4L2 driver for Samsung EXYNOS4x12 SoC series - FIMC-IS (Imaging Subsystem). - - To compile this driver as a module, choose M here: the - module will be called exynos4-fimc-is. - -config VIDEO_EXYNOS4_ISP_DMA_CAPTURE - bool "EXYNOS4x12 FIMC-IS ISP Direct DMA capture support" - depends on VIDEO_EXYNOS4_FIMC_IS - select VIDEO_EXYNOS4_IS_COMMON - default y - help - This option enables an additional video device node exposing a V4L2 - video capture interface for the FIMC-IS ISP raw (Bayer) capture DMA. - -endif # VIDEO_SAMSUNG_EXYNOS4_IS diff --git a/drivers/media/platform/exynos4-is/Makefile b/drivers/media/platform/exynos4-is/Makefile deleted file mode 100644 index a5ab01c73b95..000000000000 --- a/drivers/media/platform/exynos4-is/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-m2m.o fimc-capture.o media-dev.o -exynos-fimc-lite-objs += fimc-lite-reg.o fimc-lite.o -s5p-csis-objs := mipi-csis.o -exynos4-is-common-objs := common.o - -exynos-fimc-is-objs := fimc-is.o fimc-isp.o fimc-is-sensor.o fimc-is-regs.o -exynos-fimc-is-objs += fimc-is-param.o fimc-is-errno.o fimc-is-i2c.o - -ifeq ($(CONFIG_VIDEO_EXYNOS4_ISP_DMA_CAPTURE),y) -exynos-fimc-is-objs += fimc-isp-video.o -endif - -obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o -obj-$(CONFIG_VIDEO_EXYNOS_FIMC_LITE) += exynos-fimc-lite.o -obj-$(CONFIG_VIDEO_EXYNOS4_FIMC_IS) += exynos-fimc-is.o -obj-$(CONFIG_VIDEO_S5P_FIMC) += s5p-fimc.o -obj-$(CONFIG_VIDEO_EXYNOS4_IS_COMMON) += exynos4-is-common.o diff --git a/drivers/media/platform/exynos4-is/common.c b/drivers/media/platform/exynos4-is/common.c deleted file mode 100644 index 023f624d29d5..000000000000 --- a/drivers/media/platform/exynos4-is/common.c +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung S5P/EXYNOS4 SoC Camera Subsystem driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#include <linux/module.h> -#include <media/drv-intf/exynos-fimc.h> -#include "common.h" - -/* - * Called with the media graph mutex held or media_entity_is_streaming(entity) - * true. - */ -struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity) -{ - struct media_pad *pad = &entity->pads[0]; - struct v4l2_subdev *sd; - - while (pad->flags & MEDIA_PAD_FL_SINK) { - /* source pad */ - pad = media_entity_remote_pad(pad); - if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) - break; - - sd = media_entity_to_v4l2_subdev(pad->entity); - - if (sd->grp_id == GRP_ID_FIMC_IS_SENSOR || - sd->grp_id == GRP_ID_SENSOR) - return sd; - /* sink pad */ - pad = &sd->entity.pads[0]; - } - return NULL; -} -EXPORT_SYMBOL(fimc_find_remote_sensor); - -void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap) -{ - strscpy(cap->driver, dev->driver->name, sizeof(cap->driver)); - strscpy(cap->card, dev->driver->name, sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), - "platform:%s", dev_name(dev)); -} -EXPORT_SYMBOL(__fimc_vidioc_querycap); - -MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/exynos4-is/common.h b/drivers/media/platform/exynos4-is/common.h deleted file mode 100644 index 0389b66e5144..000000000000 --- a/drivers/media/platform/exynos4-is/common.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - */ - -#include <linux/device.h> -#include <linux/videodev2.h> -#include <media/media-entity.h> -#include <media/v4l2-subdev.h> - -struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity); -void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap); diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c deleted file mode 100644 index 7ff4024003f4..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ /dev/null @@ -1,1894 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung S5P/EXYNOS4 SoC series camera interface (camera capture) driver - * - * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#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/v4l2-rect.h> -#include <media/videobuf2-v4l2.h> -#include <media/videobuf2-dma-contig.h> - -#include "common.h" -#include "fimc-core.h" -#include "fimc-reg.h" -#include "media-dev.h" - -static int fimc_capture_hw_init(struct fimc_dev *fimc) -{ - struct fimc_source_info *si = &fimc->vid_cap.source_config; - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - int ret; - unsigned long flags; - - if (ctx == NULL || ctx->s_frame.fmt == NULL) - return -EINVAL; - - if (si->fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK) { - ret = fimc_hw_camblk_cfg_writeback(fimc); - if (ret < 0) - return ret; - } - - 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, si); - fimc_hw_set_camera_type(fimc, si); - fimc_hw_set_camera_source(fimc, si); - 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); - fimc_hw_set_output_path(ctx); - fimc_hw_set_out_dma(ctx); - if (fimc->drv_data->alpha_color) - fimc_hw_set_rgb_alpha(ctx); - clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); - } - spin_unlock_irqrestore(&fimc->slock, flags); - return ret; -} - -/* - * Reinitialize the driver so it is ready to start the streaming again. - * Set fimc->state to indicate stream off and the hardware shut down state. - * If not suspending (@suspend is false), return any buffers to videobuf2. - * Otherwise put any owned buffers onto the pending buffers queue, so they - * can be re-spun when the device is being resumed. Also perform FIMC - * software reset and disable streaming on the whole pipeline if required. - */ -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_SUSPENDED); - else - 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, 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, VB2_BUF_STATE_ERROR); - } - - fimc_hw_reset(fimc); - cap->buf_index = 0; - - spin_unlock_irqrestore(&fimc->slock, flags); - - if (streaming) - return fimc_pipeline_call(&cap->ve, set_stream, 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 - * @ctx: FIMC capture context - * - * 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. - */ -static int fimc_capture_config_update(struct fimc_ctx *ctx) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - int ret; - - fimc_hw_set_camera_offset(fimc, &ctx->s_frame); - - ret = fimc_set_scaler_info(ctx); - if (ret) - return ret; - - 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); - fimc_prepare_dma_offset(ctx, &ctx->d_frame); - fimc_hw_set_out_dma(ctx); - if (fimc->drv_data->alpha_color) - fimc_hw_set_rgb_alpha(ctx); - - clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); - return ret; -} - -void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) -{ - struct fimc_vid_cap *cap = &fimc->vid_cap; - struct fimc_pipeline *p = to_fimc_pipeline(cap->ve.pipe); - struct v4l2_subdev *csis = p->subdevs[IDX_CSIS]; - struct fimc_frame *f = &cap->ctx->d_frame; - struct fimc_vid_buffer *v_buf; - - if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) { - wake_up(&fimc->irq_queue); - goto done; - } - - if (!list_empty(&cap->active_buf_q) && - test_bit(ST_CAPT_RUN, &fimc->state) && deq_buf) { - v_buf = fimc_active_queue_pop(cap); - - v_buf->vb.vb2_buf.timestamp = ktime_get_ns(); - v_buf->vb.sequence = cap->frame_count++; - - vb2_buffer_done(&v_buf->vb.vb2_buf, 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->addr, 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; - } - /* - * Set up a buffer at MIPI-CSIS if current image format - * requires the frame embedded data capture. - */ - if (f->fmt->mdataplanes && !list_empty(&cap->active_buf_q)) { - unsigned int plane = ffs(f->fmt->mdataplanes) - 1; - unsigned int size = f->payload[plane]; - s32 index = fimc_hw_get_frame_index(fimc); - void *vaddr; - - list_for_each_entry(v_buf, &cap->active_buf_q, list) { - if (v_buf->index != index) - continue; - vaddr = vb2_plane_vaddr(&v_buf->vb.vb2_buf, plane); - v4l2_subdev_call(csis, video, s_rx_buffer, - vaddr, &size); - break; - } - } - - if (cap->active_buf_cnt == 0) { - if (deq_buf) - 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); - } - - if (test_bit(ST_CAPT_APPLY_CFG, &fimc->state)) - fimc_capture_config_update(cap->ctx); -done: - if (cap->active_buf_cnt == 1) { - fimc_deactivate_capture(fimc); - clear_bit(ST_CAPT_STREAM, &fimc->state); - } - - dbg("frame: %d, active_buf_cnt: %d", - fimc_hw_get_frame_index(fimc), cap->active_buf_cnt); -} - - -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_capture_hw_init(fimc); - if (ret) { - fimc_capture_state_cleanup(fimc, false); - return ret; - } - - 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)) - return fimc_pipeline_call(&vid_cap->ve, set_stream, 1); - } - - return 0; -} - -static void 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; - - 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_call(&fimc->vid_cap.ve, close); -} - -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 exynos_video_entity *ve = &vid_cap->ve; - 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_call(ve, open, &ve->vdev.entity, false); - fimc_capture_hw_init(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.vb2_buf); - } - return 0; - -} - -static int queue_setup(struct vb2_queue *vq, - unsigned int *num_buffers, unsigned int *num_planes, - unsigned int sizes[], struct device *alloc_devs[]) -{ - struct fimc_ctx *ctx = vq->drv_priv; - struct fimc_frame *frame = &ctx->d_frame; - struct fimc_fmt *fmt = frame->fmt; - unsigned long wh = frame->f_width * frame->f_height; - int i; - - if (fmt == NULL) - return -EINVAL; - - if (*num_planes) { - if (*num_planes != fmt->memplanes) - return -EINVAL; - for (i = 0; i < *num_planes; i++) - if (sizes[i] < (wh * fmt->depth[i]) / 8) - return -EINVAL; - return 0; - } - - *num_planes = fmt->memplanes; - - for (i = 0; i < fmt->memplanes; i++) { - unsigned int size = (wh * fmt->depth[i]) / 8; - - if (fimc_fmt_is_user_defined(fmt->color)) - sizes[i] = frame->payload[i]; - else - sizes[i] = max_t(u32, size, frame->payload[i]); - } - - 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.ve.vdev, - "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 vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct fimc_vid_buffer *buf - = container_of(vbuf, 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; - struct exynos_video_entity *ve = &vid_cap->ve; - unsigned long flags; - int min_bufs; - - spin_lock_irqsave(&fimc->slock, flags); - fimc_prepare_addr(ctx, &buf->vb.vb2_buf, &ctx->d_frame, &buf->addr); - - 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->addr, 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)) { - int ret; - - fimc_activate_capture(ctx); - spin_unlock_irqrestore(&fimc->slock, flags); - - if (test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) - return; - - ret = fimc_pipeline_call(ve, set_stream, 1); - if (ret < 0) - v4l2_err(&ve->vdev, "stream on failed: %d\n", ret); - return; - } - spin_unlock_irqrestore(&fimc->slock, flags); -} - -static const struct vb2_ops fimc_capture_qops = { - .queue_setup = queue_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .start_streaming = start_streaming, - .stop_streaming = stop_streaming, -}; - -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); - struct fimc_vid_cap *vc = &fimc->vid_cap; - struct exynos_video_entity *ve = &vc->ve; - int ret = -EBUSY; - - dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); - - mutex_lock(&fimc->lock); - - if (fimc_m2m_active(fimc)) - goto unlock; - - set_bit(ST_CAPT_BUSY, &fimc->state); - ret = pm_runtime_resume_and_get(&fimc->pdev->dev); - if (ret < 0) - goto unlock; - - ret = v4l2_fh_open(file); - if (ret) { - pm_runtime_put_sync(&fimc->pdev->dev); - goto unlock; - } - - if (v4l2_fh_is_singular_file(file)) { - fimc_md_graph_lock(ve); - - ret = fimc_pipeline_call(ve, open, &ve->vdev.entity, true); - - if (ret == 0) - ve->vdev.entity.use_count++; - - fimc_md_graph_unlock(ve); - - if (ret == 0) - ret = fimc_capture_set_default_format(fimc); - - if (ret < 0) { - clear_bit(ST_CAPT_BUSY, &fimc->state); - pm_runtime_put_sync(&fimc->pdev->dev); - v4l2_fh_release(file); - } - } -unlock: - mutex_unlock(&fimc->lock); - return ret; -} - -static int fimc_capture_release(struct file *file) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_vid_cap *vc = &fimc->vid_cap; - bool close = v4l2_fh_is_singular_file(file); - int ret; - - dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); - - mutex_lock(&fimc->lock); - - if (close && vc->streaming) { - media_pipeline_stop(&vc->ve.vdev.entity); - vc->streaming = false; - } - - ret = _vb2_fop_release(file, NULL); - - if (close) { - clear_bit(ST_CAPT_BUSY, &fimc->state); - fimc_pipeline_call(&vc->ve, close); - clear_bit(ST_CAPT_SUSPENDED, &fimc->state); - - fimc_md_graph_lock(&vc->ve); - vc->ve.vdev.entity.use_count--; - fimc_md_graph_unlock(&vc->ve); - } - - pm_runtime_put_sync(&fimc->pdev->dev); - mutex_unlock(&fimc->lock); - - return ret; -} - -static const struct v4l2_file_operations fimc_capture_fops = { - .owner = THIS_MODULE, - .open = fimc_capture_open, - .release = fimc_capture_release, - .poll = vb2_fop_poll, - .unlocked_ioctl = video_ioctl2, - .mmap = vb2_fop_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; - const struct fimc_variant *var = fimc->variant; - const 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; - - /* Conversion from/to JPEG or User Defined format is not supported */ - if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE && - fimc_fmt_is_user_defined(ctx->s_frame.fmt->color)) - *code = ctx->s_frame.fmt->mbus_code; - - if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad == FIMC_SD_PAD_SOURCE) - mask |= FMT_FLAGS_M2M; - - if (pad == FIMC_SD_PAD_SINK_FIFO) - mask = FMT_FLAGS_WRITEBACK; - - 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_SOURCE) { - max_w = fimc_fmt_is_user_defined(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_user_defined(ffmt->color) ? - 3 : 1, - 0); - return ffmt; - } - /* Can't scale or crop in transparent (JPEG) transfer mode */ - if (fimc_fmt_is_user_defined(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; - if (ctx->state & FIMC_COMPOSE) { - min_w = dst->offs_h + dst->width; - min_h = dst->offs_v + dst->height; - } else { - min_w = var->min_out_pixsize; - min_h = 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_selection(struct fimc_ctx *ctx, - struct v4l2_rect *r, - int target) -{ - bool rotate = ctx->rotation == 90 || ctx->rotation == 270; - struct fimc_dev *fimc = ctx->fimc_dev; - const struct fimc_variant *var = fimc->variant; - const 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_user_defined(ctx->d_frame.fmt->color)) { - r->width = sink->f_width; - r->height = sink->f_height; - r->left = r->top = 0; - return; - } - if (target == V4L2_SEL_TGT_COMPOSE) { - u32 tmp_min_h = ffs(sink->width) - 3; - u32 tmp_min_v = ffs(sink->height) - 1; - - if (ctx->rotation != 90 && ctx->rotation != 270) - align_h = 1; - max_sc_h = min(SCALER_MAX_HRATIO, 1 << tmp_min_h); - max_sc_v = min(SCALER_MAX_VRATIO, 1 << tmp_min_v); - 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 compose rectangle 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 (target == V4L2_SEL_TGT_COMPOSE) { - 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 crop/compose 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("target %#x: (%d,%d)/%dx%d, sink fmt: %dx%d", - target, r->left, r->top, r->width, r->height, - sink->f_width, sink->f_height); -} - -/* - * The video node ioctl operations - */ -static int fimc_cap_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct fimc_dev *fimc = video_drvdata(file); - - __fimc_vidioc_querycap(&fimc->pdev->dev, cap); - return 0; -} - -static int fimc_cap_enum_fmt(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; - f->pixelformat = fmt->fourcc; - return 0; -} - -static struct media_entity *fimc_pipeline_get_head(struct media_entity *me) -{ - struct media_pad *pad = &me->pads[0]; - - while (!(pad->flags & MEDIA_PAD_FL_SOURCE)) { - pad = media_entity_remote_pad(pad); - if (!pad) - break; - me = pad->entity; - pad = &me->pads[0]; - } - - return me; -} - -/** - * 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 fimc_pipeline *p = to_fimc_pipeline(fimc->vid_cap.ve.pipe); - struct v4l2_subdev *sd = p->subdevs[IDX_SENSOR]; - struct v4l2_subdev_format sfmt; - struct v4l2_mbus_framefmt *mf = &sfmt.format; - struct media_entity *me; - struct fimc_fmt *ffmt; - struct media_pad *pad; - int ret, i = 1; - u32 fcc; - - 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; - - me = fimc_pipeline_get_head(&sd->entity); - - 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; - - /* set format on all pipeline subdevs */ - while (me != &fimc->vid_cap.subdev.entity) { - sd = media_entity_to_v4l2_subdev(me); - - sfmt.pad = 0; - ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt); - if (ret) - return ret; - - if (me->pads[0].flags & MEDIA_PAD_FL_SINK) { - sfmt.pad = me->num_pads - 1; - mf->code = tfmt->code; - ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, - &sfmt); - if (ret) - return ret; - } - - pad = media_entity_remote_pad(&me->pads[sfmt.pad]); - if (!pad) - return -EINVAL; - me = pad->entity; - } - - if (mf->code != tfmt->code) - continue; - - 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_SINK_CAM); - 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; - break; - } - - if (fmt_id && ffmt) - *fmt_id = ffmt; - *tfmt = *mf; - - return 0; -} - -/** - * fimc_get_sensor_frame_desc - query the sensor for media bus frame parameters - * @sensor: pointer to the sensor subdev - * @plane_fmt: provides plane sizes corresponding to the frame layout entries - * @num_planes: number of planes - * @try: true to set the frame parameters, false to query only - * - * This function is used by this driver only for compressed/blob data formats. - */ -static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor, - struct v4l2_plane_pix_format *plane_fmt, - unsigned int num_planes, bool try) -{ - struct v4l2_mbus_frame_desc fd; - int i, ret; - int pad; - - for (i = 0; i < num_planes; i++) - fd.entry[i].length = plane_fmt[i].sizeimage; - - pad = sensor->entity.num_pads - 1; - if (try) - ret = v4l2_subdev_call(sensor, pad, set_frame_desc, pad, &fd); - else - ret = v4l2_subdev_call(sensor, pad, get_frame_desc, pad, &fd); - - if (ret < 0) - return ret; - - if (num_planes != fd.num_entries) - return -EINVAL; - - for (i = 0; i < num_planes; i++) - plane_fmt[i].sizeimage = fd.entry[i].length; - - if (fd.entry[0].length > FIMC_MAX_JPEG_BUF_SIZE) { - v4l2_err(sensor->v4l2_dev, "Unsupported buffer size: %u\n", - fd.entry[0].length); - - return -EINVAL; - } - - 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); - - __fimc_get_format(&fimc->vid_cap.ctx->d_frame, f); - return 0; -} - -/* - * Try or set format on the fimc.X.capture video node and additionally - * on the whole pipeline if @try is false. - * Locking: the caller must _not_ hold the graph mutex. - */ -static int __video_try_or_set_format(struct fimc_dev *fimc, - struct v4l2_format *f, bool try, - struct fimc_fmt **inp_fmt, - struct fimc_fmt **out_fmt) -{ - struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct fimc_vid_cap *vc = &fimc->vid_cap; - struct exynos_video_entity *ve = &vc->ve; - struct fimc_ctx *ctx = vc->ctx; - unsigned int width = 0, height = 0; - int ret = 0; - - /* Pre-configure format at the camera input interface, for JPEG only */ - if (fimc_jpeg_fourcc(pix->pixelformat)) { - fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SINK_CAM); - if (try) { - width = pix->width; - height = pix->height; - } else { - ctx->s_frame.f_width = pix->width; - ctx->s_frame.f_height = pix->height; - } - } - - /* Try the format at the scaler and the DMA output */ - *out_fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SOURCE); - if (*out_fmt == NULL) - return -EINVAL; - - /* Restore image width/height for JPEG (no resizing supported). */ - if (try && fimc_jpeg_fourcc(pix->pixelformat)) { - pix->width = width; - pix->height = height; - } - - /* Try to match format at the host and the sensor */ - if (!vc->user_subdev_api) { - struct v4l2_mbus_framefmt mbus_fmt; - struct v4l2_mbus_framefmt *mf; - - mf = try ? &mbus_fmt : &fimc->vid_cap.ci_fmt; - - mf->code = (*out_fmt)->mbus_code; - mf->width = pix->width; - mf->height = pix->height; - - fimc_md_graph_lock(ve); - ret = fimc_pipeline_try_format(ctx, mf, inp_fmt, try); - fimc_md_graph_unlock(ve); - - if (ret < 0) - return ret; - - pix->width = mf->width; - pix->height = mf->height; - } - - fimc_adjust_mplane_format(*out_fmt, pix->width, pix->height, pix); - - if ((*out_fmt)->flags & FMT_FLAGS_COMPRESSED) { - struct v4l2_subdev *sensor; - - fimc_md_graph_lock(ve); - - sensor = __fimc_md_get_subdev(ve->pipe, IDX_SENSOR); - if (sensor) - fimc_get_sensor_frame_desc(sensor, pix->plane_fmt, - (*out_fmt)->memplanes, try); - else - ret = -EPIPE; - - fimc_md_graph_unlock(ve); - } - - return ret; -} - -static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_fmt *out_fmt = NULL, *inp_fmt = NULL; - - return __video_try_or_set_format(fimc, f, true, &inp_fmt, &out_fmt); -} - -static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, - enum fimc_color_fmt color) -{ - bool jpeg = fimc_fmt_is_user_defined(color); - - 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_vid_cap *vc = &fimc->vid_cap; - struct fimc_ctx *ctx = vc->ctx; - struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct fimc_frame *ff = &ctx->d_frame; - struct fimc_fmt *inp_fmt = NULL; - int ret, i; - - if (vb2_is_busy(&fimc->vid_cap.vbq)) - return -EBUSY; - - ret = __video_try_or_set_format(fimc, f, false, &inp_fmt, &ff->fmt); - if (ret < 0) - return ret; - - /* Update RGB Alpha control state and value range */ - fimc_alpha_ctrl_update(ctx); - - for (i = 0; i < ff->fmt->memplanes; i++) { - ff->bytesperline[i] = pix->plane_fmt[i].bytesperline; - ff->payload[i] = pix->plane_fmt[i].sizeimage; - } - - set_frame_bounds(ff, pix->width, pix->height); - /* Reset the composition rectangle if not yet configured */ - if (!(ctx->state & FIMC_COMPOSE)) - set_frame_crop(ff, 0, 0, pix->width, pix->height); - - fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color); - - /* Reset cropping and set format at the camera interface input */ - if (!vc->user_subdev_api) { - ctx->s_frame.fmt = inp_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 exynos_video_entity *ve = &fimc->vid_cap.ve; - struct v4l2_subdev *sd; - - if (i->index != 0) - return -EINVAL; - - i->type = V4L2_INPUT_TYPE_CAMERA; - fimc_md_graph_lock(ve); - sd = __fimc_md_get_subdev(ve->pipe, IDX_SENSOR); - fimc_md_graph_unlock(ve); - - if (sd) - strscpy(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 - * @fimc: the FIMC device this context applies to - * - * 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 *vc = &fimc->vid_cap; - struct v4l2_subdev *sd = &vc->subdev; - struct fimc_pipeline *p = to_fimc_pipeline(vc->ve.pipe); - struct media_pad *sink_pad, *src_pad; - int i, ret; - - while (1) { - /* - * Find current entity sink pad and any remote sink pad linked - * to it. We stop if there is no sink pad in current entity or - * it is not linked to any other remote entity. - */ - src_pad = NULL; - - for (i = 0; i < sd->entity.num_pads; i++) { - struct media_pad *p = &sd->entity.pads[i]; - - if (p->flags & MEDIA_PAD_FL_SINK) { - sink_pad = p; - src_pad = media_entity_remote_pad(sink_pad); - if (src_pad) - break; - } - } - - if (!src_pad || !is_media_entity_v4l2_subdev(src_pad->entity)) - break; - - /* Don't call FIMC subdev operation to avoid nested locking */ - if (sd == &vc->subdev) { - struct fimc_frame *ff = &vc->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 = sink_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 */ - sd = media_entity_to_v4l2_subdev(src_pad->entity); - src_fmt.pad = src_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; - - if (sd == p->subdevs[IDX_SENSOR] && - fimc_user_defined_mbus_fmt(src_fmt.format.code)) { - struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES]; - struct fimc_frame *frame = &vc->ctx->d_frame; - unsigned int i; - - ret = fimc_get_sensor_frame_desc(sd, plane_fmt, - frame->fmt->memplanes, - false); - if (ret < 0) - return -EPIPE; - - for (i = 0; i < frame->fmt->memplanes; i++) - if (frame->payload[i] < plane_fmt[i].sizeimage) - 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_vid_cap *vc = &fimc->vid_cap; - struct media_entity *entity = &vc->ve.vdev.entity; - struct fimc_source_info *si = NULL; - struct v4l2_subdev *sd; - int ret; - - if (fimc_capture_active(fimc)) - return -EBUSY; - - ret = media_pipeline_start(entity, &vc->ve.pipe->mp); - if (ret < 0) - return ret; - - sd = __fimc_md_get_subdev(vc->ve.pipe, IDX_SENSOR); - if (sd) - si = v4l2_get_subdev_hostdata(sd); - - if (si == NULL) { - ret = -EPIPE; - goto err_p_stop; - } - /* - * Save configuration data related to currently attached image - * sensor or other data source, e.g. FIMC-IS. - */ - vc->source_config = *si; - - if (vc->input == GRP_ID_FIMC_IS) - vc->source_config.fimc_bus_type = FIMC_BUS_TYPE_ISP_WRITEBACK; - - if (vc->user_subdev_api) { - ret = fimc_pipeline_validate(fimc); - if (ret < 0) - goto err_p_stop; - } - - ret = vb2_ioctl_streamon(file, priv, type); - if (!ret) { - vc->streaming = true; - return ret; - } - -err_p_stop: - media_pipeline_stop(entity); - return ret; -} - -static int fimc_cap_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_vid_cap *vc = &fimc->vid_cap; - int ret; - - ret = vb2_ioctl_streamoff(file, priv, type); - if (ret < 0) - return ret; - - if (vc->streaming) { - media_pipeline_stop(&vc->ve.vdev.entity); - vc->streaming = false; - } - - return 0; -} - -static int fimc_cap_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) -{ - struct fimc_dev *fimc = video_drvdata(file); - int ret; - - ret = vb2_ioctl_reqbufs(file, priv, reqbufs); - - if (!ret) - fimc->vid_cap.reqbufs_count = reqbufs->count; - - return ret; -} - -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) - return -EINVAL; - - switch (s->target) { - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - f = &ctx->d_frame; - fallthrough; - 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: - f = &ctx->d_frame; - fallthrough; - case V4L2_SEL_TGT_CROP: - 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; -} - -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; - - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (s->target == V4L2_SEL_TGT_COMPOSE) - f = &ctx->d_frame; - else if (s->target == V4L2_SEL_TGT_CROP) - f = &ctx->s_frame; - else - return -EINVAL; - - fimc_capture_try_selection(ctx, &rect, s->target); - - if (s->flags & V4L2_SEL_FLAG_LE && - !v4l2_rect_enclosed(&rect, &s->r)) - return -ERANGE; - - if (s->flags & V4L2_SEL_FLAG_GE && - !v4l2_rect_enclosed(&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_cap_querycap, - - .vidioc_enum_fmt_vid_cap = fimc_cap_enum_fmt, - .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 = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_expbuf = vb2_ioctl_expbuf, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_create_bufs = vb2_ioctl_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); - struct fimc_vid_cap *vc = &fimc->vid_cap; - struct v4l2_subdev *sensor; - - if (!is_media_entity_v4l2_subdev(remote->entity)) - 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)) { - fimc->vid_cap.input = 0; - return 0; - } - - if (vc->input != 0) - return -EBUSY; - - vc->input = sd->grp_id; - - if (vc->user_subdev_api) - return 0; - - /* Inherit V4L2 controls from the image sensor subdev. */ - sensor = fimc_find_remote_sensor(&vc->subdev.entity); - if (sensor == NULL) - return 0; - - return v4l2_ctrl_add_handler(&vc->ctx->ctrls.handler, - sensor->ctrl_handler, NULL, true); -} - -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_source_info *si; - struct fimc_vid_buffer *buf; - struct fimc_md *fmd; - struct fimc_dev *fimc; - unsigned long flags; - - if (sd == NULL) - return; - - si = v4l2_get_subdev_hostdata(sd); - fmd = entity_to_fimc_mdev(&sd->entity); - - spin_lock_irqsave(&fmd->slock, flags); - - fimc = si ? source_to_sensor_info(si)->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.vb2_buf, 0, - *((u32 *)arg)); - } - fimc_capture_irq_handler(fimc, 1); - 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_state *sd_state, - 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_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct fimc_frame *ff = &ctx->s_frame; - struct v4l2_mbus_framefmt *mf; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); - fmt->format = *mf; - return 0; - } - - mf = &fmt->format; - mutex_lock(&fimc->lock); - - switch (fmt->pad) { - case FIMC_SD_PAD_SOURCE: - if (!WARN_ON(ff->fmt == NULL)) - mf->code = ff->fmt->mbus_code; - /* Sink pads crop rectangle size */ - mf->width = ff->width; - mf->height = ff->height; - break; - case FIMC_SD_PAD_SINK_FIFO: - *mf = fimc->vid_cap.wb_fmt; - break; - case FIMC_SD_PAD_SINK_CAM: - default: - *mf = fimc->vid_cap.ci_fmt; - break; - } - - mutex_unlock(&fimc->lock); - mf->colorspace = V4L2_COLORSPACE_JPEG; - - return 0; -} - -static int fimc_subdev_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *mf = &fmt->format; - struct fimc_vid_cap *vc = &fimc->vid_cap; - struct fimc_ctx *ctx = vc->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(&vc->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(sd, sd_state, fmt->pad); - *mf = fmt->format; - return 0; - } - /* There must be a bug in the driver if this happens */ - if (WARN_ON(ffmt == NULL)) - return -EINVAL; - - /* Update RGB Alpha control state and value range */ - fimc_alpha_ctrl_update(ctx); - - fimc_capture_mark_jpeg_xfer(ctx, ffmt->color); - if (fmt->pad == FIMC_SD_PAD_SOURCE) { - ff = &ctx->d_frame; - /* Sink pads crop rectangle size */ - mf->width = ctx->s_frame.width; - mf->height = ctx->s_frame.height; - } else { - ff = &ctx->s_frame; - } - - mutex_lock(&fimc->lock); - set_frame_bounds(ff, mf->width, mf->height); - - if (fmt->pad == FIMC_SD_PAD_SINK_FIFO) - vc->wb_fmt = *mf; - else if (fmt->pad == FIMC_SD_PAD_SINK_CAM) - vc->ci_fmt = *mf; - - ff->fmt = ffmt; - - /* Reset the crop rectangle if required. */ - if (!(fmt->pad == FIMC_SD_PAD_SOURCE && (ctx->state & FIMC_COMPOSE))) - set_frame_crop(ff, 0, 0, mf->width, mf->height); - - if (fmt->pad != FIMC_SD_PAD_SOURCE) - ctx->state &= ~FIMC_COMPOSE; - - mutex_unlock(&fimc->lock); - return 0; -} - -static int fimc_subdev_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_selection *sel) -{ - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct fimc_frame *f = &ctx->s_frame; - struct v4l2_rect *r = &sel->r; - struct v4l2_rect *try_sel; - - if (sel->pad == FIMC_SD_PAD_SOURCE) - return -EINVAL; - - mutex_lock(&fimc->lock); - - switch (sel->target) { - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - f = &ctx->d_frame; - fallthrough; - case V4L2_SEL_TGT_CROP_BOUNDS: - r->width = f->o_width; - r->height = f->o_height; - r->left = 0; - r->top = 0; - mutex_unlock(&fimc->lock); - return 0; - - case V4L2_SEL_TGT_CROP: - try_sel = v4l2_subdev_get_try_crop(sd, sd_state, sel->pad); - break; - case V4L2_SEL_TGT_COMPOSE: - try_sel = v4l2_subdev_get_try_compose(sd, sd_state, sel->pad); - f = &ctx->d_frame; - break; - default: - mutex_unlock(&fimc->lock); - return -EINVAL; - } - - if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { - sel->r = *try_sel; - } else { - r->left = f->offs_h; - r->top = f->offs_v; - r->width = f->width; - r->height = f->height; - } - - dbg("target %#x: l:%d, t:%d, %dx%d, f_w: %d, f_h: %d", - sel->pad, r->left, r->top, r->width, r->height, - f->f_width, f->f_height); - - mutex_unlock(&fimc->lock); - return 0; -} - -static int fimc_subdev_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_selection *sel) -{ - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct fimc_frame *f = &ctx->s_frame; - struct v4l2_rect *r = &sel->r; - struct v4l2_rect *try_sel; - unsigned long flags; - - if (sel->pad == FIMC_SD_PAD_SOURCE) - return -EINVAL; - - mutex_lock(&fimc->lock); - fimc_capture_try_selection(ctx, r, V4L2_SEL_TGT_CROP); - - switch (sel->target) { - case V4L2_SEL_TGT_CROP: - try_sel = v4l2_subdev_get_try_crop(sd, sd_state, sel->pad); - break; - case V4L2_SEL_TGT_COMPOSE: - try_sel = v4l2_subdev_get_try_compose(sd, sd_state, sel->pad); - f = &ctx->d_frame; - break; - default: - mutex_unlock(&fimc->lock); - return -EINVAL; - } - - if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { - *try_sel = sel->r; - } else { - spin_lock_irqsave(&fimc->slock, flags); - set_frame_crop(f, r->left, r->top, r->width, r->height); - set_bit(ST_CAPT_APPLY_CFG, &fimc->state); - if (sel->target == V4L2_SEL_TGT_COMPOSE) - ctx->state |= FIMC_COMPOSE; - spin_unlock_irqrestore(&fimc->slock, flags); - } - - dbg("target %#x: (%d,%d)/%dx%d", sel->target, r->left, r->top, - r->width, r->height); - - mutex_unlock(&fimc->lock); - return 0; -} - -static const struct v4l2_subdev_pad_ops fimc_subdev_pad_ops = { - .enum_mbus_code = fimc_subdev_enum_mbus_code, - .get_selection = fimc_subdev_get_selection, - .set_selection = fimc_subdev_set_selection, - .get_fmt = fimc_subdev_get_fmt, - .set_fmt = fimc_subdev_set_fmt, -}; - -static const struct v4l2_subdev_ops fimc_subdev_ops = { - .pad = &fimc_subdev_pad_ops, -}; - -/* 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 = FIMC_DEFAULT_WIDTH, - .height = FIMC_DEFAULT_HEIGHT, - .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 */ -static int fimc_register_capture_device(struct fimc_dev *fimc, - struct v4l2_device *v4l2_dev) -{ - struct video_device *vfd = &fimc->vid_cap.ve.vdev; - struct vb2_queue *q = &fimc->vid_cap.vbq; - struct fimc_ctx *ctx; - struct fimc_vid_cap *vid_cap; - struct fimc_fmt *fmt; - int ret = -ENOMEM; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - ctx->fimc_dev = fimc; - ctx->in_path = FIMC_IO_CAMERA; - ctx->out_path = FIMC_IO_DMA; - ctx->state = FIMC_CTX_CAP; - ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); - ctx->d_frame.fmt = ctx->s_frame.fmt; - - memset(vfd, 0, sizeof(*vfd)); - snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.capture", fimc->id); - - 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_empty; - vfd->queue = q; - vfd->lock = &fimc->lock; - vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE; - - video_set_drvdata(vfd, fimc); - vid_cap = &fimc->vid_cap; - vid_cap->active_buf_cnt = 0; - vid_cap->reqbufs_count = 0; - vid_cap->ctx = ctx; - - INIT_LIST_HEAD(&vid_cap->pending_buf_q); - INIT_LIST_HEAD(&vid_cap->active_buf_q); - - memset(q, 0, sizeof(*q)); - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; - q->drv_priv = ctx; - q->ops = &fimc_capture_qops; - q->mem_ops = &vb2_dma_contig_memops; - q->buf_struct_size = sizeof(struct fimc_vid_buffer); - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &fimc->lock; - q->dev = &fimc->pdev->dev; - - ret = vb2_queue_init(q); - if (ret) - goto err_free_ctx; - - /* Default format configuration */ - fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); - vid_cap->ci_fmt.width = FIMC_DEFAULT_WIDTH; - vid_cap->ci_fmt.height = FIMC_DEFAULT_HEIGHT; - vid_cap->ci_fmt.code = fmt->mbus_code; - - ctx->s_frame.width = FIMC_DEFAULT_WIDTH; - ctx->s_frame.height = FIMC_DEFAULT_HEIGHT; - ctx->s_frame.fmt = fmt; - - fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_WRITEBACK, 0); - vid_cap->wb_fmt = vid_cap->ci_fmt; - vid_cap->wb_fmt.code = fmt->mbus_code; - - vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK; - vfd->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; - ret = media_entity_pads_init(&vfd->entity, 1, &vid_cap->vd_pad); - if (ret) - goto err_free_ctx; - - ret = fimc_ctrls_create(ctx); - if (ret) - goto err_me_cleanup; - - ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); - if (ret) - goto err_ctrl_free; - - v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n", - vfd->name, video_device_node_name(vfd)); - - vfd->ctrl_handler = &ctx->ctrls.handler; - return 0; - -err_ctrl_free: - fimc_ctrls_delete(ctx); -err_me_cleanup: - media_entity_cleanup(&vfd->entity); -err_free_ctx: - kfree(ctx); - return ret; -} - -static int fimc_capture_subdev_registered(struct v4l2_subdev *sd) -{ - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - int ret; - - if (fimc == NULL) - return -ENXIO; - - ret = fimc_register_m2m_device(fimc, sd->v4l2_dev); - if (ret) - return ret; - - fimc->vid_cap.ve.pipe = v4l2_get_subdev_hostdata(sd); - - ret = fimc_register_capture_device(fimc, sd->v4l2_dev); - if (ret) { - fimc_unregister_m2m_device(fimc); - fimc->vid_cap.ve.pipe = NULL; - } - - return ret; -} - -static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd) -{ - struct fimc_dev *fimc = v4l2_get_subdevdata(sd); - struct video_device *vdev; - - if (fimc == NULL) - return; - - mutex_lock(&fimc->lock); - - fimc_unregister_m2m_device(fimc); - vdev = &fimc->vid_cap.ve.vdev; - - if (video_is_registered(vdev)) { - video_unregister_device(vdev); - media_entity_cleanup(&vdev->entity); - fimc_ctrls_delete(fimc->vid_cap.ctx); - fimc->vid_cap.ve.pipe = NULL; - } - kfree(fimc->vid_cap.ctx); - fimc->vid_cap.ctx = NULL; - - mutex_unlock(&fimc->lock); -} - -static const struct v4l2_subdev_internal_ops fimc_capture_sd_internal_ops = { - .registered = fimc_capture_subdev_registered, - .unregistered = fimc_capture_subdev_unregistered, -}; - -int fimc_initialize_capture_subdev(struct fimc_dev *fimc) -{ - struct v4l2_subdev *sd = &fimc->vid_cap.subdev; - int ret; - - v4l2_subdev_init(sd, &fimc_subdev_ops); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->id); - - fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK_CAM].flags = MEDIA_PAD_FL_SINK; - fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK_FIFO].flags = MEDIA_PAD_FL_SINK; - fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - ret = media_entity_pads_init(&sd->entity, FIMC_SD_PADS_NUM, - fimc->vid_cap.sd_pads); - if (ret) - return ret; - - sd->entity.ops = &fimc_sd_media_ops; - sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; - sd->internal_ops = &fimc_capture_sd_internal_ops; - v4l2_set_subdevdata(sd, fimc); - return 0; -} - -void fimc_unregister_capture_subdev(struct fimc_dev *fimc) -{ - struct v4l2_subdev *sd = &fimc->vid_cap.subdev; - - v4l2_device_unregister_subdev(sd); - media_entity_cleanup(&sd->entity); - v4l2_set_subdevdata(sd, NULL); -} diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c deleted file mode 100644 index 91cc8d58a663..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ /dev/null @@ -1,1179 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Samsung S5P/EXYNOS4 SoC series FIMC (CAMIF) driver - * - * Copyright (C) 2010-2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#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/mfd/syscon.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/slab.h> -#include <linux/clk.h> -#include <media/v4l2-ioctl.h> -#include <media/videobuf2-v4l2.h> -#include <media/videobuf2-dma-contig.h> - -#include "fimc-core.h" -#include "fimc-reg.h" -#include "media-dev.h" - -static char *fimc_clocks[MAX_FIMC_CLOCKS] = { - "sclk_fimc", "fimc" -}; - -static struct fimc_fmt fimc_formats[] = { - { - .fourcc = V4L2_PIX_FMT_RGB565, - .depth = { 16 }, - .color = FIMC_FMT_RGB565, - .memplanes = 1, - .colplanes = 1, - .flags = FMT_FLAGS_M2M, - }, { - .fourcc = V4L2_PIX_FMT_BGR666, - .depth = { 32 }, - .color = FIMC_FMT_RGB666, - .memplanes = 1, - .colplanes = 1, - .flags = FMT_FLAGS_M2M, - }, { - .fourcc = V4L2_PIX_FMT_BGR32, - .depth = { 32 }, - .color = FIMC_FMT_RGB888, - .memplanes = 1, - .colplanes = 1, - .flags = FMT_FLAGS_M2M | FMT_HAS_ALPHA, - }, { - .fourcc = V4L2_PIX_FMT_RGB555, - .depth = { 16 }, - .color = FIMC_FMT_RGB555, - .memplanes = 1, - .colplanes = 1, - .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA, - }, { - .fourcc = V4L2_PIX_FMT_RGB444, - .depth = { 16 }, - .color = FIMC_FMT_RGB444, - .memplanes = 1, - .colplanes = 1, - .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA, - }, { - .mbus_code = MEDIA_BUS_FMT_YUV10_1X30, - .flags = FMT_FLAGS_WRITEBACK, - }, { - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = { 16 }, - .color = FIMC_FMT_YCBYCR422, - .memplanes = 1, - .colplanes = 1, - .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, - .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, - }, { - .fourcc = V4L2_PIX_FMT_UYVY, - .depth = { 16 }, - .color = FIMC_FMT_CBYCRY422, - .memplanes = 1, - .colplanes = 1, - .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, - .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, - }, { - .fourcc = V4L2_PIX_FMT_VYUY, - .depth = { 16 }, - .color = FIMC_FMT_CRYCBY422, - .memplanes = 1, - .colplanes = 1, - .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, - .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, - }, { - .fourcc = V4L2_PIX_FMT_YVYU, - .depth = { 16 }, - .color = FIMC_FMT_YCRYCB422, - .memplanes = 1, - .colplanes = 1, - .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, - .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, - }, { - .fourcc = V4L2_PIX_FMT_YUV422P, - .depth = { 16 }, - .color = FIMC_FMT_YCBYCR422, - .memplanes = 1, - .colplanes = 3, - .flags = FMT_FLAGS_M2M, - }, { - .fourcc = V4L2_PIX_FMT_NV16, - .depth = { 16 }, - .color = FIMC_FMT_YCBYCR422, - .memplanes = 1, - .colplanes = 2, - .flags = FMT_FLAGS_M2M, - }, { - .fourcc = V4L2_PIX_FMT_NV61, - .depth = { 16 }, - .color = FIMC_FMT_YCRYCB422, - .memplanes = 1, - .colplanes = 2, - .flags = FMT_FLAGS_M2M, - }, { - .fourcc = V4L2_PIX_FMT_YUV420, - .depth = { 12 }, - .color = FIMC_FMT_YCBCR420, - .memplanes = 1, - .colplanes = 3, - .flags = FMT_FLAGS_M2M, - }, { - .fourcc = V4L2_PIX_FMT_NV12, - .depth = { 12 }, - .color = FIMC_FMT_YCBCR420, - .memplanes = 1, - .colplanes = 2, - .flags = FMT_FLAGS_M2M, - }, { - .fourcc = V4L2_PIX_FMT_NV12M, - .color = FIMC_FMT_YCBCR420, - .depth = { 8, 4 }, - .memplanes = 2, - .colplanes = 2, - .flags = FMT_FLAGS_M2M, - }, { - .fourcc = V4L2_PIX_FMT_YUV420M, - .color = FIMC_FMT_YCBCR420, - .depth = { 8, 2, 2 }, - .memplanes = 3, - .colplanes = 3, - .flags = FMT_FLAGS_M2M, - }, { - .fourcc = V4L2_PIX_FMT_NV12MT, - .color = FIMC_FMT_YCBCR420, - .depth = { 8, 4 }, - .memplanes = 2, - .colplanes = 2, - .flags = FMT_FLAGS_M2M, - }, { - .fourcc = V4L2_PIX_FMT_JPEG, - .color = FIMC_FMT_JPEG, - .depth = { 8 }, - .memplanes = 1, - .colplanes = 1, - .mbus_code = MEDIA_BUS_FMT_JPEG_1X8, - .flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED, - }, { - .fourcc = V4L2_PIX_FMT_S5C_UYVY_JPG, - .color = FIMC_FMT_YUYV_JPEG, - .depth = { 8 }, - .memplanes = 2, - .colplanes = 1, - .mdataplanes = 0x2, /* plane 1 holds frame meta data */ - .mbus_code = MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8, - .flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED, - }, -}; - -struct fimc_fmt *fimc_get_format(unsigned int index) -{ - if (index >= ARRAY_SIZE(fimc_formats)) - return NULL; - - return &fimc_formats[index]; -} - -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) -{ - const struct 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\n", 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\n", 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 irqreturn_t fimc_irq_handler(int irq, void *priv) -{ - struct fimc_dev *fimc = priv; - 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); - - if (ctx->state & FIMC_CTX_SHUT) { - ctx->state &= ~FIMC_CTX_SHUT; - wake_up(&fimc->irq_queue); - } - return IRQ_HANDLED; - } - } else if (test_bit(ST_CAPT_PEND, &fimc->state)) { - int last_buf = test_bit(ST_CAPT_JPEG, &fimc->state) && - fimc->vid_cap.reqbufs_count == 1; - fimc_capture_irq_handler(fimc, !last_buf); - } -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 *addr) -{ - 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); - - addr->y = vb2_dma_contig_plane_dma_addr(vb, 0); - - if (frame->fmt->memplanes == 1) { - switch (frame->fmt->colplanes) { - case 1: - addr->cb = 0; - addr->cr = 0; - break; - case 2: - /* decompose Y into Y/Cb */ - addr->cb = (u32)(addr->y + pix_size); - addr->cr = 0; - break; - case 3: - addr->cb = (u32)(addr->y + pix_size); - /* decompose Y into Y/Cb/Cr */ - if (FIMC_FMT_YCBCR420 == frame->fmt->color) - addr->cr = (u32)(addr->cb + (pix_size >> 2)); - else /* 422 */ - addr->cr = (u32)(addr->cb + (pix_size >> 1)); - break; - default: - return -EINVAL; - } - } else if (!frame->fmt->mdataplanes) { - if (frame->fmt->memplanes >= 2) - addr->cb = vb2_dma_contig_plane_dma_addr(vb, 1); - - if (frame->fmt->memplanes == 3) - addr->cr = vb2_dma_contig_plane_dma_addr(vb, 2); - } - - dbg("DMA ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d", - addr->y, addr->cb, addr->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 = FIMC_REG_CIOCTRL_ORDER422_2P_LSB_CRCB; - ctx->out_order_2p = FIMC_REG_CIOCTRL_ORDER422_2P_LSB_CRCB; - - /* Set order for 1 plane input formats. */ - switch (ctx->s_frame.fmt->color) { - case FIMC_FMT_YCRYCB422: - ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_YCRYCB; - break; - case FIMC_FMT_CBYCRY422: - ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_CBYCRY; - break; - case FIMC_FMT_CRYCBY422: - ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_CRYCBY; - break; - case FIMC_FMT_YCBYCR422: - default: - ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_YCBYCR; - break; - } - dbg("ctx->in_order_1p= %d", ctx->in_order_1p); - - switch (ctx->d_frame.fmt->color) { - case FIMC_FMT_YCRYCB422: - ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_YCRYCB; - break; - case FIMC_FMT_CBYCRY422: - ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_CBYCRY; - break; - case FIMC_FMT_CRYCBY422: - ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_CRYCBY; - break; - case FIMC_FMT_YCBYCR422: - default: - ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_YCBYCR; - break; - } - dbg("ctx->out_order_1p= %d", ctx->out_order_1p); -} - -void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f) -{ - bool pix_hoff = ctx->fimc_dev->drv_data->dma_pix_hoff; - u32 i, depth = 0; - - for (i = 0; i < f->fmt->memplanes; i++) - depth += f->fmt->depth[i]; - - f->dma_offset.y_h = f->offs_h; - if (!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 (!pix_hoff) { - if (f->fmt->colplanes == 3) { - f->dma_offset.cb_h >>= 1; - f->dma_offset.cr_h >>= 1; - } - if (f->fmt->color == FIMC_FMT_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); -} - -static int fimc_set_color_effect(struct fimc_ctx *ctx, enum v4l2_colorfx colorfx) -{ - struct fimc_effect *effect = &ctx->effect; - - switch (colorfx) { - case V4L2_COLORFX_NONE: - effect->type = FIMC_REG_CIIMGEFF_FIN_BYPASS; - break; - case V4L2_COLORFX_BW: - effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY; - effect->pat_cb = 128; - effect->pat_cr = 128; - break; - case V4L2_COLORFX_SEPIA: - effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY; - effect->pat_cb = 115; - effect->pat_cr = 145; - break; - case V4L2_COLORFX_NEGATIVE: - effect->type = FIMC_REG_CIIMGEFF_FIN_NEGATIVE; - break; - case V4L2_COLORFX_EMBOSS: - effect->type = FIMC_REG_CIIMGEFF_FIN_EMBOSSING; - break; - case V4L2_COLORFX_ART_FREEZE: - effect->type = FIMC_REG_CIIMGEFF_FIN_ARTFREEZE; - break; - case V4L2_COLORFX_SILHOUETTE: - effect->type = FIMC_REG_CIIMGEFF_FIN_SILHOUETTE; - break; - case V4L2_COLORFX_SET_CBCR: - effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY; - effect->pat_cb = ctx->ctrls.colorfx_cbcr->val >> 8; - effect->pat_cr = ctx->ctrls.colorfx_cbcr->val & 0xff; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * V4L2 controls handling - */ -#define ctrl_to_ctx(__ctrl) \ - container_of((__ctrl)->handler, struct fimc_ctx, ctrls.handler) - -static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - const struct fimc_variant *variant = fimc->variant; - 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)) { - 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; - - case V4L2_CID_COLORFX: - ret = fimc_set_color_effect(ctx, ctrl->val); - if (ret) - return ret; - 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->fimc_dev->slock, flags); - ret = __fimc_s_ctrl(ctx, ctrl); - spin_unlock_irqrestore(&ctx->fimc_dev->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) -{ - unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt); - struct fimc_ctrls *ctrls = &ctx->ctrls; - struct v4l2_ctrl_handler *handler = &ctrls->handler; - - if (ctx->ctrls.ready) - return 0; - - v4l2_ctrl_handler_init(handler, 6); - - ctrls->rotate = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops, - V4L2_CID_ROTATE, 0, 270, 90, 0); - ctrls->hflip = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - ctrls->vflip = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - - if (ctx->fimc_dev->drv_data->alpha_color) - ctrls->alpha = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops, - V4L2_CID_ALPHA_COMPONENT, - 0, max_alpha, 1, 0); - else - ctrls->alpha = NULL; - - ctrls->colorfx = v4l2_ctrl_new_std_menu(handler, &fimc_ctrl_ops, - V4L2_CID_COLORFX, V4L2_COLORFX_SET_CBCR, - ~0x983f, V4L2_COLORFX_NONE); - - ctrls->colorfx_cbcr = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops, - V4L2_CID_COLORFX_CBCR, 0, 0xffff, 1, 0); - - ctx->effect.type = FIMC_REG_CIIMGEFF_FIN_BYPASS; - - if (!handler->error) { - v4l2_ctrl_cluster(2, &ctrls->colorfx); - ctrls->ready = true; - } - - return handler->error; -} - -void fimc_ctrls_delete(struct fimc_ctx *ctx) -{ - struct fimc_ctrls *ctrls = &ctx->ctrls; - - if (ctrls->ready) { - v4l2_ctrl_handler_free(&ctrls->handler); - ctrls->ready = false; - ctrls->alpha = NULL; - } -} - -void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active) -{ - unsigned int has_alpha = ctx->d_frame.fmt->flags & FMT_HAS_ALPHA; - struct fimc_ctrls *ctrls = &ctx->ctrls; - - if (!ctrls->ready) - return; - - mutex_lock(ctrls->handler.lock); - v4l2_ctrl_activate(ctrls->rotate, active); - v4l2_ctrl_activate(ctrls->hflip, active); - v4l2_ctrl_activate(ctrls->vflip, active); - v4l2_ctrl_activate(ctrls->colorfx, active); - if (ctrls->alpha) - v4l2_ctrl_activate(ctrls->alpha, active && has_alpha); - - if (active) { - fimc_set_color_effect(ctx, ctrls->colorfx->cur.val); - ctx->rotation = ctrls->rotate->val; - ctx->hflip = ctrls->hflip->val; - ctx->vflip = ctrls->vflip->val; - } else { - ctx->effect.type = FIMC_REG_CIIMGEFF_FIN_BYPASS; - ctx->rotation = 0; - ctx->hflip = 0; - ctx->vflip = 0; - } - mutex_unlock(ctrls->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->ctrls.alpha; - - if (ctrl == NULL || !fimc->drv_data->alpha_color) - 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); -} - -void __fimc_get_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) { - pixm->plane_fmt[i].bytesperline = frame->bytesperline[i]; - pixm->plane_fmt[i].sizeimage = frame->payload[i]; - } -} - -/** - * 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) { - struct v4l2_plane_pix_format *plane_fmt = &pix->plane_fmt[i]; - u32 bpl = plane_fmt->bytesperline; - u32 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; - /* - * Currently bytesperline for each plane is same, except - * V4L2_PIX_FMT_YUV420M format. This calculation may need - * to be changed when other multi-planar formats are added - * to the fimc_formats[] array. - */ - if (i == 0) - bytesperline = bpl; - else if (i == 1 && fmt->memplanes == 3) - bytesperline /= 2; - - plane_fmt->bytesperline = bytesperline; - sizeimage = pix->width * pix->height * fmt->depth[i] / 8; - - /* Ensure full last row for tiled formats */ - if (tiled_fmt(fmt)) { - /* 64 * 32 * plane_fmt->bytesperline / 64 */ - u32 row_size = plane_fmt->bytesperline * 32; - - sizeimage = roundup(sizeimage, row_size); - } - - plane_fmt->sizeimage = max(sizeimage, plane_fmt->sizeimage); - } -} - -/** - * 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 void fimc_clk_put(struct fimc_dev *fimc) -{ - int i; - for (i = 0; i < MAX_FIMC_CLOCKS; i++) { - if (IS_ERR(fimc->clock[i])) - continue; - clk_unprepare(fimc->clock[i]); - clk_put(fimc->clock[i]); - fimc->clock[i] = ERR_PTR(-EINVAL); - } -} - -static int fimc_clk_get(struct fimc_dev *fimc) -{ - int i, ret; - - for (i = 0; i < MAX_FIMC_CLOCKS; i++) - fimc->clock[i] = ERR_PTR(-EINVAL); - - for (i = 0; i < MAX_FIMC_CLOCKS; i++) { - fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); - if (IS_ERR(fimc->clock[i])) { - ret = PTR_ERR(fimc->clock[i]); - goto err; - } - ret = clk_prepare(fimc->clock[i]); - if (ret < 0) { - clk_put(fimc->clock[i]); - fimc->clock[i] = ERR_PTR(-EINVAL); - 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; -} - -#ifdef CONFIG_PM -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) -{ - struct fimc_ctx *ctx; - unsigned long flags; - - spin_lock_irqsave(&fimc->slock, flags); - /* Clear for full H/W setup in first run after resume */ - ctx = fimc->m2m.ctx; - fimc->m2m.ctx = NULL; - spin_unlock_irqrestore(&fimc->slock, flags); - - if (test_and_clear_bit(ST_M2M_SUSPENDED, &fimc->state)) - fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); - - return 0; -} -#endif /* CONFIG_PM */ - -static const struct of_device_id fimc_of_match[]; - -static int fimc_parse_dt(struct fimc_dev *fimc, u32 *clk_freq) -{ - struct device *dev = &fimc->pdev->dev; - struct device_node *node = dev->of_node; - const struct of_device_id *of_id; - struct fimc_variant *v; - struct fimc_pix_limit *lim; - u32 args[FIMC_PIX_LIMITS_MAX]; - int ret; - - if (of_property_read_bool(node, "samsung,lcd-wb")) - return -ENODEV; - - v = devm_kzalloc(dev, sizeof(*v) + sizeof(*lim), GFP_KERNEL); - if (!v) - return -ENOMEM; - - of_id = of_match_node(fimc_of_match, node); - if (!of_id) - return -EINVAL; - fimc->drv_data = of_id->data; - ret = of_property_read_u32_array(node, "samsung,pix-limits", - args, FIMC_PIX_LIMITS_MAX); - if (ret < 0) - return ret; - - lim = (struct fimc_pix_limit *)&v[1]; - - lim->scaler_en_w = args[0]; - lim->scaler_dis_w = args[1]; - lim->out_rot_en_w = args[2]; - lim->out_rot_dis_w = args[3]; - v->pix_limit = lim; - - ret = of_property_read_u32_array(node, "samsung,min-pix-sizes", - args, 2); - v->min_inp_pixsize = ret ? FIMC_DEF_MIN_SIZE : args[0]; - v->min_out_pixsize = ret ? FIMC_DEF_MIN_SIZE : args[1]; - ret = of_property_read_u32_array(node, "samsung,min-pix-alignment", - args, 2); - v->min_vsize_align = ret ? FIMC_DEF_HEIGHT_ALIGN : args[0]; - v->hor_offs_align = ret ? FIMC_DEF_HOR_OFFS_ALIGN : args[1]; - - ret = of_property_read_u32(node, "samsung,rotators", &args[1]); - v->has_inp_rot = ret ? 1 : args[1] & 0x01; - v->has_out_rot = ret ? 1 : args[1] & 0x10; - v->has_mainscaler_ext = of_property_read_bool(node, - "samsung,mainscaler-ext"); - - v->has_isp_wb = of_property_read_bool(node, "samsung,isp-wb"); - v->has_cam_if = of_property_read_bool(node, "samsung,cam-if"); - of_property_read_u32(node, "clock-frequency", clk_freq); - fimc->id = of_alias_get_id(node, "fimc"); - - fimc->variant = v; - return 0; -} - -static int fimc_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - u32 lclk_freq = 0; - struct fimc_dev *fimc; - struct resource *res; - int ret = 0; - int irq; - - fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL); - if (!fimc) - return -ENOMEM; - - fimc->pdev = pdev; - - if (dev->of_node) { - ret = fimc_parse_dt(fimc, &lclk_freq); - if (ret < 0) - return ret; - } else { - fimc->drv_data = fimc_get_drvdata(pdev); - fimc->id = pdev->id; - } - if (!fimc->drv_data || fimc->id >= fimc->drv_data->num_entities || - fimc->id < 0) { - dev_err(dev, "Invalid driver data or device id (%d)\n", - fimc->id); - return -EINVAL; - } - if (!dev->of_node) - fimc->variant = fimc->drv_data->variant[fimc->id]; - - init_waitqueue_head(&fimc->irq_queue); - spin_lock_init(&fimc->slock); - mutex_init(&fimc->lock); - - if (fimc->variant->has_isp_wb) { - fimc->sysreg = fimc_get_sysreg_regmap(dev->of_node); - if (IS_ERR(fimc->sysreg)) - return PTR_ERR(fimc->sysreg); - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - fimc->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(fimc->regs)) - return PTR_ERR(fimc->regs); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - ret = fimc_clk_get(fimc); - if (ret) - return ret; - - if (lclk_freq == 0) - lclk_freq = fimc->drv_data->lclk_frequency; - - ret = clk_set_rate(fimc->clock[CLK_BUS], lclk_freq); - if (ret < 0) - return ret; - - ret = clk_enable(fimc->clock[CLK_BUS]); - if (ret < 0) - return ret; - - ret = devm_request_irq(dev, irq, fimc_irq_handler, - 0, dev_name(dev), fimc); - if (ret < 0) { - dev_err(dev, "failed to install irq (%d)\n", ret); - goto err_sclk; - } - - ret = fimc_initialize_capture_subdev(fimc); - if (ret < 0) - goto err_sclk; - - platform_set_drvdata(pdev, fimc); - pm_runtime_enable(dev); - - if (!pm_runtime_enabled(dev)) { - ret = clk_enable(fimc->clock[CLK_GATE]); - if (ret < 0) - goto err_sd; - } - - vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); - - dev_dbg(dev, "FIMC.%d registered successfully\n", fimc->id); - return 0; - -err_sd: - fimc_unregister_capture_subdev(fimc); -err_sclk: - clk_disable(fimc->clock[CLK_BUS]); - fimc_clk_put(fimc); - return ret; -} - -#ifdef CONFIG_PM -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 initialization */ - 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; -} -#endif - -#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 fimc_remove(struct platform_device *pdev) -{ - struct fimc_dev *fimc = platform_get_drvdata(pdev); - - pm_runtime_disable(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - clk_disable(fimc->clock[CLK_GATE]); - pm_runtime_set_suspended(&pdev->dev); - - fimc_unregister_capture_subdev(fimc); - vb2_dma_contig_clear_max_seg_size(&pdev->dev); - - clk_disable(fimc->clock[CLK_BUS]); - fimc_clk_put(fimc); - - dev_info(&pdev->dev, "driver unloaded\n"); - return 0; -} - -/* S5PV210, S5PC110 */ -static const struct fimc_drvdata fimc_drvdata_s5pv210 = { - .num_entities = 3, - .lclk_frequency = 166000000UL, - .out_buf_count = 4, - .dma_pix_hoff = 1, -}; - -/* EXYNOS4210, S5PV310, S5PC210 */ -static const struct fimc_drvdata fimc_drvdata_exynos4210 = { - .num_entities = 4, - .lclk_frequency = 166000000UL, - .dma_pix_hoff = 1, - .cistatus2 = 1, - .alpha_color = 1, - .out_buf_count = 32, -}; - -/* EXYNOS4412 */ -static const struct fimc_drvdata fimc_drvdata_exynos4x12 = { - .num_entities = 4, - .lclk_frequency = 166000000UL, - .dma_pix_hoff = 1, - .cistatus2 = 1, - .alpha_color = 1, - .out_buf_count = 32, -}; - -static const struct of_device_id fimc_of_match[] = { - { - .compatible = "samsung,s5pv210-fimc", - .data = &fimc_drvdata_s5pv210, - }, { - .compatible = "samsung,exynos4210-fimc", - .data = &fimc_drvdata_exynos4210, - }, { - .compatible = "samsung,exynos4212-fimc", - .data = &fimc_drvdata_exynos4x12, - }, - { /* sentinel */ }, -}; - -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 = fimc_remove, - .driver = { - .of_match_table = fimc_of_match, - .name = FIMC_DRIVER_NAME, - .pm = &fimc_pm_ops, - } -}; - -int __init fimc_register_driver(void) -{ - return platform_driver_register(&fimc_driver); -} - -void __exit fimc_unregister_driver(void) -{ - platform_driver_unregister(&fimc_driver); -} diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h deleted file mode 100644 index 7a058f3e6298..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ /dev/null @@ -1,725 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd. - */ - -#ifndef FIMC_CORE_H_ -#define FIMC_CORE_H_ - -/*#define DEBUG*/ - -#include <linux/platform_device.h> -#include <linux/regmap.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/mfd/syscon.h> -#include <linux/types.h> -#include <linux/videodev2.h> -#include <linux/io.h> -#include <linux/sizes.h> - -#include <media/media-entity.h> -#include <media/videobuf2-v4l2.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> -#include <media/v4l2-mem2mem.h> -#include <media/v4l2-mediabus.h> -#include <media/drv-intf/exynos-fimc.h> - -#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_DRIVER_NAME "exynos4-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 -#define FIMC_MAX_JPEG_BUF_SIZE (10 * SZ_1M) -#define FIMC_MAX_PLANES 3 -#define FIMC_PIX_LIMITS_MAX 4 -#define FIMC_DEF_MIN_SIZE 16 -#define FIMC_DEF_HEIGHT_ALIGN 2 -#define FIMC_DEF_HOR_OFFS_ALIGN 1 -#define FIMC_DEFAULT_WIDTH 640 -#define FIMC_DEFAULT_HEIGHT 480 - -/* 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_IO_NONE, - FIMC_IO_CAMERA, - FIMC_IO_DMA, - FIMC_IO_LCDFIFO, - FIMC_IO_WRITEBACK, - FIMC_IO_ISP, -}; - -enum fimc_color_fmt { - FIMC_FMT_RGB444 = 0x10, - FIMC_FMT_RGB555, - FIMC_FMT_RGB565, - FIMC_FMT_RGB666, - FIMC_FMT_RGB888, - FIMC_FMT_RGB30_LOCAL, - FIMC_FMT_YCBCR420 = 0x20, - FIMC_FMT_YCBYCR422, - FIMC_FMT_YCRYCB422, - FIMC_FMT_CBYCRY422, - FIMC_FMT_CRYCBY422, - FIMC_FMT_YCBCR444_LOCAL, - FIMC_FMT_RAW8 = 0x40, - FIMC_FMT_RAW10, - FIMC_FMT_RAW12, - FIMC_FMT_JPEG = 0x80, - FIMC_FMT_YUYV_JPEG = 0x100, -}; - -#define fimc_fmt_is_user_defined(x) (!!((x) & 0x180)) -#define fimc_fmt_is_rgb(x) (!!((x) & 0x10)) - -#define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \ - __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - -/* The hardware context state. */ -#define FIMC_PARAMS (1 << 0) -#define FIMC_COMPOSE (1 << 1) -#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_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 address set for DMA - * @y: luminance plane address - * @cb: Cb plane address - * @cr: Cr plane 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 - * @addr: precalculated DMA address set - * @index: buffer index for the output DMA engine - */ -struct fimc_vid_buffer { - struct vb2_v4l2_buffer vb; - struct list_head list; - struct fimc_addr addr; - 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) - * @bytesperline: bytesperline value for each plane - * @addr: image frame buffer DMA addresses - * @dma_offset: DMA offset in bytes - * @fmt: fimc color format pointer - * @alpha: alpha value - */ -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 int payload[VIDEO_MAX_PLANES]; - unsigned int bytesperline[VIDEO_MAX_PLANES]; - struct fimc_addr addr; - 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_CAM 0 -#define FIMC_SD_PAD_SINK_FIFO 1 -#define FIMC_SD_PAD_SOURCE 2 -#define FIMC_SD_PADS_NUM 3 - -/** - * struct fimc_vid_cap - camera capture device information - * @ctx: hardware context data - * @subdev: subdev exposing the FIMC processing block - * @ve: exynos video device entity structure - * @vd_pad: fimc video capture node pad - * @sd_pads: fimc video processing block pads - * @ci_fmt: image format at the FIMC camera input (and the scaler output) - * @wb_fmt: image format at the FIMC ISP Writeback input - * @source_config: external image source related configuration structure - * @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 - * @streaming: is streaming in progress? - * @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 v4l2_subdev subdev; - struct exynos_video_entity ve; - struct media_pad vd_pad; - struct media_pad sd_pads[FIMC_SD_PADS_NUM]; - struct v4l2_mbus_framefmt ci_fmt; - struct v4l2_mbus_framefmt wb_fmt; - struct fimc_source_info source_config; - 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; - bool streaming; - 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 fimc_variant - FIMC device variant information - * @has_inp_rot: set if has input rotator - * @has_out_rot: set if has output rotator - * @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 - * @has_isp_wb: set if this instance has ISP writeback input - * @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 alignment - * @min_vsize_align: minimum vertical pixel size alignment - */ -struct fimc_variant { - unsigned int has_inp_rot:1; - unsigned int has_out_rot:1; - unsigned int has_mainscaler_ext:1; - unsigned int has_cam_if:1; - unsigned int has_isp_wb:1; - const struct fimc_pix_limit *pix_limit; - u16 min_inp_pixsize; - u16 min_out_pixsize; - u16 hor_offs_align; - u16 min_vsize_align; -}; - -/** - * struct fimc_drvdata - per device type driver data - * @variant: variant information for this device - * @num_entities: number of fimc instances available in a SoC - * @lclk_frequency: local bus clock frequency - * @cistatus2: 1 if the FIMC IPs have CISTATUS2 register - * @dma_pix_hoff: the horizontal DMA offset unit: 1 - pixels, 0 - bytes - * @alpha_color: 1 if alpha color component is supported - * @out_buf_count: maximum number of output DMA buffers supported - */ -struct fimc_drvdata { - const struct fimc_variant *variant[FIMC_MAX_DEVS]; - int num_entities; - unsigned long lclk_frequency; - /* Fields common to all FIMC IP instances */ - u8 cistatus2; - u8 dma_pix_hoff; - u8 alpha_color; - u8 out_buf_count; -}; - -#define fimc_get_drvdata(_pdev) \ - ((struct fimc_drvdata *) platform_get_device_id(_pdev)->driver_data) - -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 - * @sysreg: pointer to the SYSREG regmap - * @variant: the IP variant information - * @drv_data: driver data - * @id: FIMC device index (0..FIMC_MAX_DEVS) - * @clock: clocks required for FIMC operation - * @regs: the mapped hardware registers - * @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 - */ -struct fimc_dev { - spinlock_t slock; - struct mutex lock; - struct platform_device *pdev; - struct s5p_platform_fimc *pdata; - struct regmap *sysreg; - const struct fimc_variant *variant; - const struct fimc_drvdata *drv_data; - int id; - struct clk *clock[MAX_FIMC_CLOCKS]; - void __iomem *regs; - 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 fimc_ctrls - v4l2 controls structure - * @handler: the control handler - * @colorfx: image effect control - * @colorfx_cbcr: Cb/Cr coefficients control - * @rotate: image rotation control - * @hflip: horizontal flip control - * @vflip: vertical flip control - * @alpha: RGB alpha control - * @ready: true if @handler is initialized - */ -struct fimc_ctrls { - struct v4l2_ctrl_handler handler; - struct { - struct v4l2_ctrl *colorfx; - struct v4l2_ctrl *colorfx_cbcr; - }; - struct v4l2_ctrl *rotate; - struct v4l2_ctrl *hflip; - struct v4l2_ctrl *vflip; - struct v4l2_ctrl *alpha; - bool ready; -}; - -/** - * struct fimc_ctx - the device context data - * @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 - * @fh: v4l2 file handle - * @ctrls: v4l2 controls structure - */ -struct fimc_ctx { - 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_fh fh; - struct fimc_ctrls ctrls; -}; - -#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_set(u32 state, struct fimc_ctx *ctx) -{ - unsigned long flags; - - spin_lock_irqsave(&ctx->fimc_dev->slock, flags); - ctx->state |= state; - spin_unlock_irqrestore(&ctx->fimc_dev->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->fimc_dev->slock, flags); - ret = (ctx->state & mask) == mask; - spin_unlock_irqrestore(&ctx->fimc_dev->slock, flags); - return ret; -} - -static inline int tiled_fmt(struct fimc_fmt *fmt) -{ - return fmt->fourcc == V4L2_PIX_FMT_NV12MT; -} - -static inline bool fimc_jpeg_fourcc(u32 pixelformat) -{ - return (pixelformat == V4L2_PIX_FMT_JPEG || - pixelformat == V4L2_PIX_FMT_S5C_UYVY_JPG); -} - -static inline bool fimc_user_defined_mbus_fmt(u32 code) -{ - return (code == MEDIA_BUS_FMT_JPEG_1X8 || - code == MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8); -} - -/* Return the alpha component bit mask */ -static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt) -{ - switch (fmt->color) { - case FIMC_FMT_RGB444: return 0x0f; - case FIMC_FMT_RGB555: return 0x01; - case FIMC_FMT_RGB888: return 0xff; - default: return 0; - }; -} - -static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx, - enum v4l2_buf_type type) -{ - struct fimc_frame *frame; - - if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || - type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - if (fimc_ctx_state_is_set(FIMC_CTX_M2M, ctx)) - frame = &ctx->s_frame; - else - return ERR_PTR(-EINVAL); - } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || - type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - 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; -} - -/* -----------------------------------------------------*/ -/* 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); -void __fimc_get_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); -struct fimc_fmt *fimc_get_format(unsigned 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 *addr); -void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f); -void fimc_set_yuv_order(struct fimc_ctx *ctx); -void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf); - -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); - -#ifdef CONFIG_MFD_SYSCON -static inline struct regmap * fimc_get_sysreg_regmap(struct device_node *node) -{ - return syscon_regmap_lookup_by_phandle(node, "samsung,sysreg"); -} -#else -#define fimc_get_sysreg_regmap(node) (NULL) -#endif - -/* -----------------------------------------------------*/ -/* fimc-m2m.c */ -void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state); - -/* -----------------------------------------------------*/ -/* fimc-capture.c */ -int fimc_initialize_capture_subdev(struct fimc_dev *fimc); -void fimc_unregister_capture_subdev(struct fimc_dev *fimc); -int fimc_capture_ctrls_create(struct fimc_dev *fimc); -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); - -/* - * Buffer list manipulation functions. Must be called with fimc.slock held. - */ - -/** - * fimc_active_queue_add - add buffer to the capture active buffers queue - * @vid_cap: camera capture device information - * @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 - * @vid_cap: camera capture device information - * - * 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 - * @vid_cap: camera capture device information - * @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 - * @vid_cap: camera capture device information - * - * 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/drivers/media/platform/exynos4-is/fimc-is-command.h b/drivers/media/platform/exynos4-is/fimc-is-command.h deleted file mode 100644 index 87978609ad55..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-command.h +++ /dev/null @@ -1,134 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung Exynos4x12 FIMC-IS (Imaging Subsystem) driver - * - * FIMC-IS command set definitions - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * - * Authors: Younghwan Joo <yhwan.joo@samsung.com> - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#ifndef FIMC_IS_CMD_H_ -#define FIMC_IS_CMD_H_ - -#define FIMC_IS_COMMAND_VER 110 /* FIMC-IS command set version 1.10 */ - -/* Enumeration of commands between the FIMC-IS and the host processor. */ - -/* HOST to FIMC-IS */ -#define HIC_PREVIEW_STILL 0x0001 -#define HIC_PREVIEW_VIDEO 0x0002 -#define HIC_CAPTURE_STILL 0x0003 -#define HIC_CAPTURE_VIDEO 0x0004 -#define HIC_STREAM_ON 0x0005 -#define HIC_STREAM_OFF 0x0006 -#define HIC_SET_PARAMETER 0x0007 -#define HIC_GET_PARAMETER 0x0008 -#define HIC_SET_TUNE 0x0009 -#define HIC_GET_STATUS 0x000b -/* Sensor part */ -#define HIC_OPEN_SENSOR 0x000c -#define HIC_CLOSE_SENSOR 0x000d -#define HIC_SIMMIAN_INIT 0x000e -#define HIC_SIMMIAN_WRITE 0x000f -#define HIC_SIMMIAN_READ 0x0010 -#define HIC_POWER_DOWN 0x0011 -#define HIC_GET_SET_FILE_ADDR 0x0012 -#define HIC_LOAD_SET_FILE 0x0013 -#define HIC_MSG_CONFIG 0x0014 -#define HIC_MSG_TEST 0x0015 -/* FIMC-IS to HOST */ -#define IHC_GET_SENSOR_NUM 0x1000 -#define IHC_SET_SHOT_MARK 0x1001 -/* parameter1: frame number */ -/* parameter2: confidence level (smile 0~100) */ -/* parameter3: confidence level (blink 0~100) */ -#define IHC_SET_FACE_MARK 0x1002 -/* parameter1: coordinate count */ -/* parameter2: coordinate buffer address */ -#define IHC_FRAME_DONE 0x1003 -/* parameter1: frame start number */ -/* parameter2: frame count */ -#define IHC_AA_DONE 0x1004 -#define IHC_NOT_READY 0x1005 - -#define IH_REPLY_DONE 0x2000 -#define IH_REPLY_NOT_DONE 0x2001 - -enum fimc_is_scenario { - IS_SC_PREVIEW_STILL, - IS_SC_PREVIEW_VIDEO, - IS_SC_CAPTURE_STILL, - IS_SC_CAPTURE_VIDEO, - IS_SC_MAX -}; - -enum fimc_is_sub_scenario { - IS_SC_SUB_DEFAULT, - IS_SC_SUB_PS_VTCALL, - IS_SC_SUB_CS_VTCALL, - IS_SC_SUB_PV_VTCALL, - IS_SC_SUB_CV_VTCALL, -}; - -struct is_common_regs { - u32 hicmd; - u32 hic_sensorid; - u32 hic_param[4]; - u32 reserved1[4]; - - u32 ihcmd; - u32 ihc_sensorid; - u32 ihc_param[4]; - u32 reserved2[4]; - - u32 isp_sensor_id; - u32 isp_param[2]; - u32 reserved3[1]; - - u32 scc_sensor_id; - u32 scc_param[2]; - u32 reserved4[1]; - - u32 dnr_sensor_id; - u32 dnr_param[2]; - u32 reserved5[1]; - - u32 scp_sensor_id; - u32 scp_param[2]; - u32 reserved6[29]; -} __packed; - -struct is_mcuctl_reg { - u32 mcuctl; - u32 bboar; - - u32 intgr0; - u32 intcr0; - u32 intmr0; - u32 intsr0; - u32 intmsr0; - - u32 intgr1; - u32 intcr1; - u32 intmr1; - u32 intsr1; - u32 intmsr1; - - u32 intcr2; - u32 intmr2; - u32 intsr2; - u32 intmsr2; - - u32 gpoctrl; - u32 cpoenctlr; - u32 gpictlr; - - u32 reserved[0xd]; - - struct is_common_regs common; -} __packed; - -#endif /* FIMC_IS_CMD_H_ */ diff --git a/drivers/media/platform/exynos4-is/fimc-is-errno.c b/drivers/media/platform/exynos4-is/fimc-is-errno.c deleted file mode 100644 index 5d9f4c1cdc5e..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-errno.c +++ /dev/null @@ -1,269 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung Exynos4 SoC series FIMC-IS slave interface driver - * - * Error log interface functions - * - * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. - * - * Authors: Younghwan Joo <yhwan.joo@samsung.com> - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#include "fimc-is-errno.h" - -const char *fimc_is_param_strerr(unsigned int error) -{ - switch (error) { - case ERROR_COMMON_CMD: - return "ERROR_COMMON_CMD: Invalid Command"; - case ERROR_COMMON_PARAMETER: - return "ERROR_COMMON_PARAMETER: Invalid Parameter"; - case ERROR_COMMON_SETFILE_LOAD: - return "ERROR_COMMON_SETFILE_LOAD: Illegal Setfile Loading"; - case ERROR_COMMON_SETFILE_ADJUST: - return "ERROR_COMMON_SETFILE_ADJUST: Setfile isn't adjusted"; - case ERROR_COMMON_SETFILE_INDEX: - return "ERROR_COMMON_SETFILE_INDEX: Invalid setfile index"; - case ERROR_COMMON_INPUT_PATH: - return "ERROR_COMMON_INPUT_PATH: Input path can be changed in ready state"; - case ERROR_COMMON_INPUT_INIT: - return "ERROR_COMMON_INPUT_INIT: IP can not start if input path is not set"; - case ERROR_COMMON_OUTPUT_PATH: - return "ERROR_COMMON_OUTPUT_PATH: Output path can be changed in ready state (stop)"; - case ERROR_COMMON_OUTPUT_INIT: - return "ERROR_COMMON_OUTPUT_INIT: IP can not start if output path is not set"; - case ERROR_CONTROL_BYPASS: - return "ERROR_CONTROL_BYPASS"; - case ERROR_OTF_INPUT_FORMAT: - return "ERROR_OTF_INPUT_FORMAT: Invalid format (DRC: YUV444, FD: YUV444, 422, 420)"; - case ERROR_OTF_INPUT_WIDTH: - return "ERROR_OTF_INPUT_WIDTH: Invalid width (DRC: 128~8192, FD: 32~8190)"; - case ERROR_OTF_INPUT_HEIGHT: - return "ERROR_OTF_INPUT_HEIGHT: Invalid bit-width (DRC: 8~12bits, FD: 8bit)"; - case ERROR_OTF_INPUT_BIT_WIDTH: - return "ERROR_OTF_INPUT_BIT_WIDTH: Invalid bit-width (DRC: 8~12bits, FD: 8bit)"; - case ERROR_DMA_INPUT_WIDTH: - return "ERROR_DMA_INPUT_WIDTH: Invalid width (DRC: 128~8192, FD: 32~8190)"; - case ERROR_DMA_INPUT_HEIGHT: - return "ERROR_DMA_INPUT_HEIGHT: Invalid height (DRC: 64~8192, FD: 16~8190)"; - case ERROR_DMA_INPUT_FORMAT: - return "ERROR_DMA_INPUT_FORMAT: Invalid format (DRC: YUV444 or YUV422, FD: YUV444,422,420)"; - case ERROR_DMA_INPUT_BIT_WIDTH: - return "ERROR_DMA_INPUT_BIT_WIDTH: Invalid bit-width (DRC: 8~12bits, FD: 8bit)"; - case ERROR_DMA_INPUT_ORDER: - return "ERROR_DMA_INPUT_ORDER: Invalid order(DRC: YYCbCr,YCbYCr,FD:NO,YYCbCr,YCbYCr,CbCr,CrCb)"; - case ERROR_DMA_INPUT_PLANE: - return "ERROR_DMA_INPUT_PLANE: Invalid palne (DRC: 3, FD: 1, 2, 3)"; - case ERROR_OTF_OUTPUT_WIDTH: - return "ERROR_OTF_OUTPUT_WIDTH: Invalid width (DRC: 128~8192)"; - case ERROR_OTF_OUTPUT_HEIGHT: - return "ERROR_OTF_OUTPUT_HEIGHT: Invalid height (DRC: 64~8192)"; - case ERROR_OTF_OUTPUT_FORMAT: - return "ERROR_OTF_OUTPUT_FORMAT: Invalid format (DRC: YUV444)"; - case ERROR_OTF_OUTPUT_BIT_WIDTH: - return "ERROR_OTF_OUTPUT_BIT_WIDTH: Invalid bit-width (DRC: 8~12bits, FD: 8bit)"; - case ERROR_DMA_OUTPUT_WIDTH: - return "ERROR_DMA_OUTPUT_WIDTH"; - case ERROR_DMA_OUTPUT_HEIGHT: - return "ERROR_DMA_OUTPUT_HEIGHT"; - case ERROR_DMA_OUTPUT_FORMAT: - return "ERROR_DMA_OUTPUT_FORMAT"; - case ERROR_DMA_OUTPUT_BIT_WIDTH: - return "ERROR_DMA_OUTPUT_BIT_WIDTH"; - case ERROR_DMA_OUTPUT_PLANE: - return "ERROR_DMA_OUTPUT_PLANE"; - case ERROR_DMA_OUTPUT_ORDER: - return "ERROR_DMA_OUTPUT_ORDER"; - - /* Sensor Error(100~199) */ - case ERROR_SENSOR_I2C_FAIL: - return "ERROR_SENSOR_I2C_FAIL"; - case ERROR_SENSOR_INVALID_FRAMERATE: - return "ERROR_SENSOR_INVALID_FRAMERATE"; - case ERROR_SENSOR_INVALID_EXPOSURETIME: - return "ERROR_SENSOR_INVALID_EXPOSURETIME"; - case ERROR_SENSOR_INVALID_SIZE: - return "ERROR_SENSOR_INVALID_SIZE"; - case ERROR_SENSOR_INVALID_SETTING: - return "ERROR_SENSOR_INVALID_SETTING"; - case ERROR_SENSOR_ACTUATOR_INIT_FAIL: - return "ERROR_SENSOR_ACTUATOR_INIT_FAIL"; - case ERROR_SENSOR_INVALID_AF_POS: - return "ERROR_SENSOR_INVALID_AF_POS"; - case ERROR_SENSOR_UNSUPPORT_FUNC: - return "ERROR_SENSOR_UNSUPPORT_FUNC"; - case ERROR_SENSOR_UNSUPPORT_PERI: - return "ERROR_SENSOR_UNSUPPORT_PERI"; - case ERROR_SENSOR_UNSUPPORT_AF: - return "ERROR_SENSOR_UNSUPPORT_AF"; - - /* ISP Error (200~299) */ - case ERROR_ISP_AF_BUSY: - return "ERROR_ISP_AF_BUSY"; - case ERROR_ISP_AF_INVALID_COMMAND: - return "ERROR_ISP_AF_INVALID_COMMAND"; - case ERROR_ISP_AF_INVALID_MODE: - return "ERROR_ISP_AF_INVALID_MODE"; - - /* DRC Error (300~399) */ - /* FD Error (400~499) */ - case ERROR_FD_CONFIG_MAX_NUMBER_STATE: - return "ERROR_FD_CONFIG_MAX_NUMBER_STATE"; - case ERROR_FD_CONFIG_MAX_NUMBER_INVALID: - return "ERROR_FD_CONFIG_MAX_NUMBER_INVALID"; - case ERROR_FD_CONFIG_YAW_ANGLE_STATE: - return "ERROR_FD_CONFIG_YAW_ANGLE_STATE"; - case ERROR_FD_CONFIG_YAW_ANGLE_INVALID: - return "ERROR_FD_CONFIG_YAW_ANGLE_INVALID\n"; - case ERROR_FD_CONFIG_ROLL_ANGLE_STATE: - return "ERROR_FD_CONFIG_ROLL_ANGLE_STATE"; - case ERROR_FD_CONFIG_ROLL_ANGLE_INVALID: - return "ERROR_FD_CONFIG_ROLL_ANGLE_INVALID"; - case ERROR_FD_CONFIG_SMILE_MODE_INVALID: - return "ERROR_FD_CONFIG_SMILE_MODE_INVALID"; - case ERROR_FD_CONFIG_BLINK_MODE_INVALID: - return "ERROR_FD_CONFIG_BLINK_MODE_INVALID"; - case ERROR_FD_CONFIG_EYES_DETECT_INVALID: - return "ERROR_FD_CONFIG_EYES_DETECT_INVALID"; - case ERROR_FD_CONFIG_MOUTH_DETECT_INVALID: - return "ERROR_FD_CONFIG_MOUTH_DETECT_INVALID"; - case ERROR_FD_CONFIG_ORIENTATION_STATE: - return "ERROR_FD_CONFIG_ORIENTATION_STATE"; - case ERROR_FD_CONFIG_ORIENTATION_INVALID: - return "ERROR_FD_CONFIG_ORIENTATION_INVALID"; - case ERROR_FD_CONFIG_ORIENTATION_VALUE_INVALID: - return "ERROR_FD_CONFIG_ORIENTATION_VALUE_INVALID"; - case ERROR_FD_RESULT: - return "ERROR_FD_RESULT"; - case ERROR_FD_MODE: - return "ERROR_FD_MODE"; - default: - return "Unknown"; - } -} - -const char *fimc_is_strerr(unsigned int error) -{ - error &= ~IS_ERROR_TIME_OUT_FLAG; - - switch (error) { - /* General */ - case IS_ERROR_INVALID_COMMAND: - return "IS_ERROR_INVALID_COMMAND"; - case IS_ERROR_REQUEST_FAIL: - return "IS_ERROR_REQUEST_FAIL"; - case IS_ERROR_INVALID_SCENARIO: - return "IS_ERROR_INVALID_SCENARIO"; - case IS_ERROR_INVALID_SENSORID: - return "IS_ERROR_INVALID_SENSORID"; - case IS_ERROR_INVALID_MODE_CHANGE: - return "IS_ERROR_INVALID_MODE_CHANGE"; - case IS_ERROR_INVALID_MAGIC_NUMBER: - return "IS_ERROR_INVALID_MAGIC_NUMBER"; - case IS_ERROR_INVALID_SETFILE_HDR: - return "IS_ERROR_INVALID_SETFILE_HDR"; - case IS_ERROR_BUSY: - return "IS_ERROR_BUSY"; - case IS_ERROR_SET_PARAMETER: - return "IS_ERROR_SET_PARAMETER"; - case IS_ERROR_INVALID_PATH: - return "IS_ERROR_INVALID_PATH"; - case IS_ERROR_OPEN_SENSOR_FAIL: - return "IS_ERROR_OPEN_SENSOR_FAIL"; - case IS_ERROR_ENTRY_MSG_THREAD_DOWN: - return "IS_ERROR_ENTRY_MSG_THREAD_DOWN"; - case IS_ERROR_ISP_FRAME_END_NOT_DONE: - return "IS_ERROR_ISP_FRAME_END_NOT_DONE"; - case IS_ERROR_DRC_FRAME_END_NOT_DONE: - return "IS_ERROR_DRC_FRAME_END_NOT_DONE"; - case IS_ERROR_SCALERC_FRAME_END_NOT_DONE: - return "IS_ERROR_SCALERC_FRAME_END_NOT_DONE"; - case IS_ERROR_ODC_FRAME_END_NOT_DONE: - return "IS_ERROR_ODC_FRAME_END_NOT_DONE"; - case IS_ERROR_DIS_FRAME_END_NOT_DONE: - return "IS_ERROR_DIS_FRAME_END_NOT_DONE"; - case IS_ERROR_TDNR_FRAME_END_NOT_DONE: - return "IS_ERROR_TDNR_FRAME_END_NOT_DONE"; - case IS_ERROR_SCALERP_FRAME_END_NOT_DONE: - return "IS_ERROR_SCALERP_FRAME_END_NOT_DONE"; - case IS_ERROR_WAIT_STREAM_OFF_NOT_DONE: - return "IS_ERROR_WAIT_STREAM_OFF_NOT_DONE"; - case IS_ERROR_NO_MSG_IS_RECEIVED: - return "IS_ERROR_NO_MSG_IS_RECEIVED"; - case IS_ERROR_SENSOR_MSG_FAIL: - return "IS_ERROR_SENSOR_MSG_FAIL"; - case IS_ERROR_ISP_MSG_FAIL: - return "IS_ERROR_ISP_MSG_FAIL"; - case IS_ERROR_DRC_MSG_FAIL: - return "IS_ERROR_DRC_MSG_FAIL"; - case IS_ERROR_LHFD_MSG_FAIL: - return "IS_ERROR_LHFD_MSG_FAIL"; - case IS_ERROR_UNKNOWN: - return "IS_ERROR_UNKNOWN"; - - /* Sensor */ - case IS_ERROR_SENSOR_PWRDN_FAIL: - return "IS_ERROR_SENSOR_PWRDN_FAIL"; - - /* ISP */ - case IS_ERROR_ISP_PWRDN_FAIL: - return "IS_ERROR_ISP_PWRDN_FAIL"; - case IS_ERROR_ISP_MULTIPLE_INPUT: - return "IS_ERROR_ISP_MULTIPLE_INPUT"; - case IS_ERROR_ISP_ABSENT_INPUT: - return "IS_ERROR_ISP_ABSENT_INPUT"; - case IS_ERROR_ISP_ABSENT_OUTPUT: - return "IS_ERROR_ISP_ABSENT_OUTPUT"; - case IS_ERROR_ISP_NONADJACENT_OUTPUT: - return "IS_ERROR_ISP_NONADJACENT_OUTPUT"; - case IS_ERROR_ISP_FORMAT_MISMATCH: - return "IS_ERROR_ISP_FORMAT_MISMATCH"; - case IS_ERROR_ISP_WIDTH_MISMATCH: - return "IS_ERROR_ISP_WIDTH_MISMATCH"; - case IS_ERROR_ISP_HEIGHT_MISMATCH: - return "IS_ERROR_ISP_HEIGHT_MISMATCH"; - case IS_ERROR_ISP_BITWIDTH_MISMATCH: - return "IS_ERROR_ISP_BITWIDTH_MISMATCH"; - case IS_ERROR_ISP_FRAME_END_TIME_OUT: - return "IS_ERROR_ISP_FRAME_END_TIME_OUT"; - - /* DRC */ - case IS_ERROR_DRC_PWRDN_FAIL: - return "IS_ERROR_DRC_PWRDN_FAIL"; - case IS_ERROR_DRC_MULTIPLE_INPUT: - return "IS_ERROR_DRC_MULTIPLE_INPUT"; - case IS_ERROR_DRC_ABSENT_INPUT: - return "IS_ERROR_DRC_ABSENT_INPUT"; - case IS_ERROR_DRC_NONADJACENT_INPUT: - return "IS_ERROR_DRC_NONADJACENT_INPUT"; - case IS_ERROR_DRC_ABSENT_OUTPUT: - return "IS_ERROR_DRC_ABSENT_OUTPUT"; - case IS_ERROR_DRC_NONADJACENT_OUTPUT: - return "IS_ERROR_DRC_NONADJACENT_OUTPUT"; - case IS_ERROR_DRC_FORMAT_MISMATCH: - return "IS_ERROR_DRC_FORMAT_MISMATCH"; - case IS_ERROR_DRC_WIDTH_MISMATCH: - return "IS_ERROR_DRC_WIDTH_MISMATCH"; - case IS_ERROR_DRC_HEIGHT_MISMATCH: - return "IS_ERROR_DRC_HEIGHT_MISMATCH"; - case IS_ERROR_DRC_BITWIDTH_MISMATCH: - return "IS_ERROR_DRC_BITWIDTH_MISMATCH"; - case IS_ERROR_DRC_FRAME_END_TIME_OUT: - return "IS_ERROR_DRC_FRAME_END_TIME_OUT"; - - /* FD */ - case IS_ERROR_FD_PWRDN_FAIL: - return "IS_ERROR_FD_PWRDN_FAIL"; - case IS_ERROR_FD_MULTIPLE_INPUT: - return "IS_ERROR_FD_MULTIPLE_INPUT"; - case IS_ERROR_FD_ABSENT_INPUT: - return "IS_ERROR_FD_ABSENT_INPUT"; - case IS_ERROR_FD_NONADJACENT_INPUT: - return "IS_ERROR_FD_NONADJACENT_INPUT"; - case IS_ERROR_LHFD_FRAME_END_TIME_OUT: - return "IS_ERROR_LHFD_FRAME_END_TIME_OUT"; - default: - return "Unknown"; - } -} diff --git a/drivers/media/platform/exynos4-is/fimc-is-errno.h b/drivers/media/platform/exynos4-is/fimc-is-errno.h deleted file mode 100644 index da36b48b8f9f..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-errno.h +++ /dev/null @@ -1,245 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung Exynos4 SoC series FIMC-IS slave interface driver - * - * FIMC-IS error code definition - * - * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. - * - * Authors: Younghwan Joo <yhwan.joo@samsung.com> - * Sylwester Nawrocki <s.nawrocki@samsung.com> -*/ - -#ifndef FIMC_IS_ERR_H_ -#define FIMC_IS_ERR_H_ - -#define IS_ERROR_VER 011 /* IS ERROR VERSION 0.11 */ - -enum { - IS_ERROR_NONE, - - /* General 1 ~ 99 */ - IS_ERROR_INVALID_COMMAND, - IS_ERROR_REQUEST_FAIL, - IS_ERROR_INVALID_SCENARIO, - IS_ERROR_INVALID_SENSORID, - IS_ERROR_INVALID_MODE_CHANGE, - IS_ERROR_INVALID_MAGIC_NUMBER, - IS_ERROR_INVALID_SETFILE_HDR, - IS_ERROR_BUSY, - IS_ERROR_SET_PARAMETER, - IS_ERROR_INVALID_PATH, - IS_ERROR_OPEN_SENSOR_FAIL, - IS_ERROR_ENTRY_MSG_THREAD_DOWN, - IS_ERROR_ISP_FRAME_END_NOT_DONE, - IS_ERROR_DRC_FRAME_END_NOT_DONE, - IS_ERROR_SCALERC_FRAME_END_NOT_DONE, - IS_ERROR_ODC_FRAME_END_NOT_DONE, - IS_ERROR_DIS_FRAME_END_NOT_DONE, - IS_ERROR_TDNR_FRAME_END_NOT_DONE, - IS_ERROR_SCALERP_FRAME_END_NOT_DONE, - IS_ERROR_WAIT_STREAM_OFF_NOT_DONE, - IS_ERROR_NO_MSG_IS_RECEIVED, - IS_ERROR_SENSOR_MSG_FAIL, - IS_ERROR_ISP_MSG_FAIL, - IS_ERROR_DRC_MSG_FAIL, - IS_ERROR_SCALERC_MSG_FAIL, - IS_ERROR_ODC_MSG_FAIL, - IS_ERROR_DIS_MSG_FAIL, - IS_ERROR_TDNR_MSG_FAIL, - IS_ERROR_SCALERP_MSG_FAIL, - IS_ERROR_LHFD_MSG_FAIL, - IS_ERROR_LHFD_INTERNAL_STOP, - - /* Sensor 100 ~ 199 */ - IS_ERROR_SENSOR_PWRDN_FAIL = 100, - IS_ERROR_SENSOR_STREAM_ON_FAIL, - IS_ERROR_SENSOR_STREAM_OFF_FAIL, - - /* ISP 200 ~ 299 */ - IS_ERROR_ISP_PWRDN_FAIL = 200, - IS_ERROR_ISP_MULTIPLE_INPUT, - IS_ERROR_ISP_ABSENT_INPUT, - IS_ERROR_ISP_ABSENT_OUTPUT, - IS_ERROR_ISP_NONADJACENT_OUTPUT, - IS_ERROR_ISP_FORMAT_MISMATCH, - IS_ERROR_ISP_WIDTH_MISMATCH, - IS_ERROR_ISP_HEIGHT_MISMATCH, - IS_ERROR_ISP_BITWIDTH_MISMATCH, - IS_ERROR_ISP_FRAME_END_TIME_OUT, - - /* DRC 300 ~ 399 */ - IS_ERROR_DRC_PWRDN_FAIL = 300, - IS_ERROR_DRC_MULTIPLE_INPUT, - IS_ERROR_DRC_ABSENT_INPUT, - IS_ERROR_DRC_NONADJACENT_INPUT, - IS_ERROR_DRC_ABSENT_OUTPUT, - IS_ERROR_DRC_NONADJACENT_OUTPUT, - IS_ERROR_DRC_FORMAT_MISMATCH, - IS_ERROR_DRC_WIDTH_MISMATCH, - IS_ERROR_DRC_HEIGHT_MISMATCH, - IS_ERROR_DRC_BITWIDTH_MISMATCH, - IS_ERROR_DRC_FRAME_END_TIME_OUT, - - /* SCALERC 400 ~ 499 */ - IS_ERROR_SCALERC_PWRDN_FAIL = 400, - - /* ODC 500 ~ 599 */ - IS_ERROR_ODC_PWRDN_FAIL = 500, - - /* DIS 600 ~ 699 */ - IS_ERROR_DIS_PWRDN_FAIL = 600, - - /* TDNR 700 ~ 799 */ - IS_ERROR_TDNR_PWRDN_FAIL = 700, - - /* SCALERC 800 ~ 899 */ - IS_ERROR_SCALERP_PWRDN_FAIL = 800, - - /* FD 900 ~ 999 */ - IS_ERROR_FD_PWRDN_FAIL = 900, - IS_ERROR_FD_MULTIPLE_INPUT, - IS_ERROR_FD_ABSENT_INPUT, - IS_ERROR_FD_NONADJACENT_INPUT, - IS_ERROR_LHFD_FRAME_END_TIME_OUT, - - IS_ERROR_UNKNOWN = 1000, -}; - -#define IS_ERROR_TIME_OUT_FLAG 0x80000000 - -/* Set parameter error enum */ -enum fimc_is_error { - /* Common error (0~99) */ - ERROR_COMMON_NONE = 0, - ERROR_COMMON_CMD = 1, /* Invalid command */ - ERROR_COMMON_PARAMETER = 2, /* Invalid parameter */ - /* setfile is not loaded before adjusting */ - ERROR_COMMON_SETFILE_LOAD = 3, - /* setfile is not Adjusted before runnng. */ - ERROR_COMMON_SETFILE_ADJUST = 4, - /* Index of setfile is not valid (0~MAX_SETFILE_NUM-1) */ - ERROR_COMMON_SETFILE_INDEX = 5, - /* Input path can be changed in ready state(stop) */ - ERROR_COMMON_INPUT_PATH = 6, - /* IP can not start if input path is not set */ - ERROR_COMMON_INPUT_INIT = 7, - /* Output path can be changed in ready state (stop) */ - ERROR_COMMON_OUTPUT_PATH = 8, - /* IP can not start if output path is not set */ - ERROR_COMMON_OUTPUT_INIT = 9, - - ERROR_CONTROL_NONE = ERROR_COMMON_NONE, - ERROR_CONTROL_BYPASS = 11, /* Enable or Disable */ - - ERROR_OTF_INPUT_NONE = ERROR_COMMON_NONE, - ERROR_OTF_INPUT_CMD = 21, - /* invalid format (DRC: YUV444, FD: YUV444, 422, 420) */ - ERROR_OTF_INPUT_FORMAT = 22, - /* invalid width (DRC: 128~8192, FD: 32~8190) */ - ERROR_OTF_INPUT_WIDTH = 23, - /* invalid height (DRC: 64~8192, FD: 16~8190) */ - ERROR_OTF_INPUT_HEIGHT = 24, - /* invalid bit-width (DRC: 8~12bits, FD: 8bit) */ - ERROR_OTF_INPUT_BIT_WIDTH = 25, - /* invalid FrameTime for ISP */ - ERROR_OTF_INPUT_USER_FRAMETIIME = 26, - - ERROR_DMA_INPUT_NONE = ERROR_COMMON_NONE, - /* invalid width (DRC: 128~8192, FD: 32~8190) */ - ERROR_DMA_INPUT_WIDTH = 31, - /* invalid height (DRC: 64~8192, FD: 16~8190) */ - ERROR_DMA_INPUT_HEIGHT = 32, - /* invalid format (DRC: YUV444 or YUV422, FD: YUV444, 422, 420) */ - ERROR_DMA_INPUT_FORMAT = 33, - /* invalid bit-width (DRC: 8~12bit, FD: 8bit) */ - ERROR_DMA_INPUT_BIT_WIDTH = 34, - /* invalid order(DRC: YYCbCrorYCbYCr, FD:NO,YYCbCr,YCbYCr,CbCr,CrCb) */ - ERROR_DMA_INPUT_ORDER = 35, - /* invalid palne (DRC: 3, FD: 1, 2, 3) */ - ERROR_DMA_INPUT_PLANE = 36, - - ERROR_OTF_OUTPUT_NONE = ERROR_COMMON_NONE, - /* invalid width (DRC: 128~8192) */ - ERROR_OTF_OUTPUT_WIDTH = 41, - /* invalid height (DRC: 64~8192) */ - ERROR_OTF_OUTPUT_HEIGHT = 42, - /* invalid format (DRC: YUV444) */ - ERROR_OTF_OUTPUT_FORMAT = 43, - /* invalid bit-width (DRC: 8~12bits) */ - ERROR_OTF_OUTPUT_BIT_WIDTH = 44, - - ERROR_DMA_OUTPUT_NONE = ERROR_COMMON_NONE, - ERROR_DMA_OUTPUT_WIDTH = 51, /* invalid width */ - ERROR_DMA_OUTPUT_HEIGHT = 52, /* invalid height */ - ERROR_DMA_OUTPUT_FORMAT = 53, /* invalid format */ - ERROR_DMA_OUTPUT_BIT_WIDTH = 54, /* invalid bit-width */ - ERROR_DMA_OUTPUT_PLANE = 55, /* invalid plane */ - ERROR_DMA_OUTPUT_ORDER = 56, /* invalid order */ - - ERROR_GLOBAL_SHOTMODE_NONE = ERROR_COMMON_NONE, - - /* SENSOR Error(100~199) */ - ERROR_SENSOR_NONE = ERROR_COMMON_NONE, - ERROR_SENSOR_I2C_FAIL = 101, - ERROR_SENSOR_INVALID_FRAMERATE, - ERROR_SENSOR_INVALID_EXPOSURETIME, - ERROR_SENSOR_INVALID_SIZE, - ERROR_SENSOR_INVALID_SETTING, - ERROR_SENSOR_ACTUATOR_INIT_FAIL, - ERROR_SENSOR_INVALID_AF_POS, - ERROR_SENSOR_UNSUPPORT_FUNC, - ERROR_SENSOR_UNSUPPORT_PERI, - ERROR_SENSOR_UNSUPPORT_AF, - - /* ISP Error (200~299) */ - ERROR_ISP_AF_NONE = ERROR_COMMON_NONE, - ERROR_ISP_AF_BUSY = 201, - ERROR_ISP_AF_INVALID_COMMAND = 202, - ERROR_ISP_AF_INVALID_MODE = 203, - ERROR_ISP_FLASH_NONE = ERROR_COMMON_NONE, - ERROR_ISP_AWB_NONE = ERROR_COMMON_NONE, - ERROR_ISP_IMAGE_EFFECT_NONE = ERROR_COMMON_NONE, - ERROR_ISP_ISO_NONE = ERROR_COMMON_NONE, - ERROR_ISP_ADJUST_NONE = ERROR_COMMON_NONE, - ERROR_ISP_METERING_NONE = ERROR_COMMON_NONE, - ERROR_ISP_AFC_NONE = ERROR_COMMON_NONE, - - /* DRC Error (300~399) */ - - /* FD Error (400~499) */ - ERROR_FD_NONE = ERROR_COMMON_NONE, - /* Invalid max number (1~16) */ - ERROR_FD_CONFIG_MAX_NUMBER_STATE = 401, - ERROR_FD_CONFIG_MAX_NUMBER_INVALID = 402, - ERROR_FD_CONFIG_YAW_ANGLE_STATE = 403, - ERROR_FD_CONFIG_YAW_ANGLE_INVALID = 404, - ERROR_FD_CONFIG_ROLL_ANGLE_STATE = 405, - ERROR_FD_CONFIG_ROLL_ANGLE_INVALID = 406, - ERROR_FD_CONFIG_SMILE_MODE_INVALID = 407, - ERROR_FD_CONFIG_BLINK_MODE_INVALID = 408, - ERROR_FD_CONFIG_EYES_DETECT_INVALID = 409, - ERROR_FD_CONFIG_MOUTH_DETECT_INVALID = 410, - ERROR_FD_CONFIG_ORIENTATION_STATE = 411, - ERROR_FD_CONFIG_ORIENTATION_INVALID = 412, - ERROR_FD_CONFIG_ORIENTATION_VALUE_INVALID = 413, - /* PARAM_FdResultStr can be only applied in ready-state or stream off */ - ERROR_FD_RESULT = 414, - /* PARAM_FdModeStr can be only applied in ready-state or stream off */ - ERROR_FD_MODE = 415, - /* Scaler Error (500 ~ 599) */ - ERROR_SCALER_NO_NONE = ERROR_COMMON_NONE, - ERROR_SCALER_DMA_OUTSEL = 501, - ERROR_SCALER_H_RATIO = 502, - ERROR_SCALER_V_RATIO = 503, - - ERROR_SCALER_IMAGE_EFFECT = 510, - - ERROR_SCALER_ROTATE = 520, - ERROR_SCALER_FLIP = 521, -}; - -const char *fimc_is_strerr(unsigned int error); -const char *fimc_is_param_strerr(unsigned int error); - -#endif /* FIMC_IS_ERR_H_ */ diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c deleted file mode 100644 index 83a28ef8e099..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * - * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#include <linux/clk.h> -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/slab.h> -#include "fimc-is-i2c.h" - -struct fimc_is_i2c { - struct i2c_adapter adapter; - struct clk *clock; -}; - -/* - * An empty algorithm is used as the actual I2C bus controller driver - * is implemented in the FIMC-IS subsystem firmware and the host CPU - * doesn't access the I2C bus controller. - */ -static u32 is_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C; -} - -static const struct i2c_algorithm fimc_is_i2c_algorithm = { - .functionality = is_i2c_func, -}; - -static int fimc_is_i2c_probe(struct platform_device *pdev) -{ - struct device_node *node = pdev->dev.of_node; - struct fimc_is_i2c *isp_i2c; - struct i2c_adapter *i2c_adap; - int ret; - - isp_i2c = devm_kzalloc(&pdev->dev, sizeof(*isp_i2c), GFP_KERNEL); - if (!isp_i2c) - return -ENOMEM; - - isp_i2c->clock = devm_clk_get(&pdev->dev, "i2c_isp"); - if (IS_ERR(isp_i2c->clock)) { - dev_err(&pdev->dev, "failed to get the clock\n"); - return PTR_ERR(isp_i2c->clock); - } - - i2c_adap = &isp_i2c->adapter; - i2c_adap->dev.of_node = node; - i2c_adap->dev.parent = &pdev->dev; - strscpy(i2c_adap->name, "exynos4x12-isp-i2c", sizeof(i2c_adap->name)); - i2c_adap->owner = THIS_MODULE; - i2c_adap->algo = &fimc_is_i2c_algorithm; - i2c_adap->class = I2C_CLASS_SPD; - - platform_set_drvdata(pdev, isp_i2c); - pm_runtime_enable(&pdev->dev); - - ret = i2c_add_adapter(i2c_adap); - if (ret < 0) - goto err_pm_dis; - /* - * Client drivers of this adapter don't do any I2C transfers as that - * is handled by the ISP firmware. But we rely on the runtime PM - * state propagation from the clients up to the adapter driver so - * clear the ignore_children flags here. PM rutnime calls are not - * used in probe() handler of clients of this adapter so there is - * no issues with clearing the flag right after registering the I2C - * adapter. - */ - pm_suspend_ignore_children(&i2c_adap->dev, false); - return 0; - -err_pm_dis: - pm_runtime_disable(&pdev->dev); - return ret; -} - -static int fimc_is_i2c_remove(struct platform_device *pdev) -{ - struct fimc_is_i2c *isp_i2c = platform_get_drvdata(pdev); - - pm_runtime_disable(&pdev->dev); - i2c_del_adapter(&isp_i2c->adapter); - - return 0; -} - -#ifdef CONFIG_PM -static int fimc_is_i2c_runtime_suspend(struct device *dev) -{ - struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev); - - clk_disable_unprepare(isp_i2c->clock); - return 0; -} - -static int fimc_is_i2c_runtime_resume(struct device *dev) -{ - struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev); - - return clk_prepare_enable(isp_i2c->clock); -} -#endif - -#ifdef CONFIG_PM_SLEEP -static int fimc_is_i2c_suspend(struct device *dev) -{ - if (pm_runtime_suspended(dev)) - return 0; - - return fimc_is_i2c_runtime_suspend(dev); -} - -static int fimc_is_i2c_resume(struct device *dev) -{ - if (pm_runtime_suspended(dev)) - return 0; - - return fimc_is_i2c_runtime_resume(dev); -} -#endif - -static const struct dev_pm_ops fimc_is_i2c_pm_ops = { - SET_RUNTIME_PM_OPS(fimc_is_i2c_runtime_suspend, - fimc_is_i2c_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(fimc_is_i2c_suspend, fimc_is_i2c_resume) -}; - -static const struct of_device_id fimc_is_i2c_of_match[] = { - { .compatible = FIMC_IS_I2C_COMPATIBLE }, - { }, -}; - -static struct platform_driver fimc_is_i2c_driver = { - .probe = fimc_is_i2c_probe, - .remove = fimc_is_i2c_remove, - .driver = { - .of_match_table = fimc_is_i2c_of_match, - .name = "fimc-isp-i2c", - .pm = &fimc_is_i2c_pm_ops, - } -}; - -int fimc_is_register_i2c_driver(void) -{ - return platform_driver_register(&fimc_is_i2c_driver); -} - -void fimc_is_unregister_i2c_driver(void) -{ - platform_driver_unregister(&fimc_is_i2c_driver); -} diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.h b/drivers/media/platform/exynos4-is/fimc-is-i2c.h deleted file mode 100644 index a23bd20be6c8..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-i2c.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#define FIMC_IS_I2C_COMPATIBLE "samsung,exynos4212-i2c-isp" - -int fimc_is_register_i2c_driver(void); -void fimc_is_unregister_i2c_driver(void); diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.c b/drivers/media/platform/exynos4-is/fimc-is-param.c deleted file mode 100644 index 9c816ae3b3e5..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-param.c +++ /dev/null @@ -1,893 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * - * Authors: Younghwan Joo <yhwan.joo@samsung.com> - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ -#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__ - -#include <linux/bitops.h> -#include <linux/bug.h> -#include <linux/device.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/types.h> -#include <linux/videodev2.h> - -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> - -#include "fimc-is.h" -#include "fimc-is-command.h" -#include "fimc-is-errno.h" -#include "fimc-is-param.h" -#include "fimc-is-regs.h" -#include "fimc-is-sensor.h" - -static void __hw_param_copy(void *dst, void *src) -{ - memcpy(dst, src, FIMC_IS_PARAM_MAX_SIZE); -} - -static void __fimc_is_hw_update_param_global_shotmode(struct fimc_is *is) -{ - struct param_global_shotmode *dst, *src; - - dst = &is->is_p_region->parameter.global.shotmode; - src = &is->config[is->config_index].global.shotmode; - __hw_param_copy(dst, src); -} - -static void __fimc_is_hw_update_param_sensor_framerate(struct fimc_is *is) -{ - struct param_sensor_framerate *dst, *src; - - dst = &is->is_p_region->parameter.sensor.frame_rate; - src = &is->config[is->config_index].sensor.frame_rate; - __hw_param_copy(dst, src); -} - -int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset) -{ - struct is_param_region *par = &is->is_p_region->parameter; - struct chain_config *cfg = &is->config[is->config_index]; - - switch (offset) { - case PARAM_ISP_CONTROL: - __hw_param_copy(&par->isp.control, &cfg->isp.control); - break; - - case PARAM_ISP_OTF_INPUT: - __hw_param_copy(&par->isp.otf_input, &cfg->isp.otf_input); - break; - - case PARAM_ISP_DMA1_INPUT: - __hw_param_copy(&par->isp.dma1_input, &cfg->isp.dma1_input); - break; - - case PARAM_ISP_DMA2_INPUT: - __hw_param_copy(&par->isp.dma2_input, &cfg->isp.dma2_input); - break; - - case PARAM_ISP_AA: - __hw_param_copy(&par->isp.aa, &cfg->isp.aa); - break; - - case PARAM_ISP_FLASH: - __hw_param_copy(&par->isp.flash, &cfg->isp.flash); - break; - - case PARAM_ISP_AWB: - __hw_param_copy(&par->isp.awb, &cfg->isp.awb); - break; - - case PARAM_ISP_IMAGE_EFFECT: - __hw_param_copy(&par->isp.effect, &cfg->isp.effect); - break; - - case PARAM_ISP_ISO: - __hw_param_copy(&par->isp.iso, &cfg->isp.iso); - break; - - case PARAM_ISP_ADJUST: - __hw_param_copy(&par->isp.adjust, &cfg->isp.adjust); - break; - - case PARAM_ISP_METERING: - __hw_param_copy(&par->isp.metering, &cfg->isp.metering); - break; - - case PARAM_ISP_AFC: - __hw_param_copy(&par->isp.afc, &cfg->isp.afc); - break; - - case PARAM_ISP_OTF_OUTPUT: - __hw_param_copy(&par->isp.otf_output, &cfg->isp.otf_output); - break; - - case PARAM_ISP_DMA1_OUTPUT: - __hw_param_copy(&par->isp.dma1_output, &cfg->isp.dma1_output); - break; - - case PARAM_ISP_DMA2_OUTPUT: - __hw_param_copy(&par->isp.dma2_output, &cfg->isp.dma2_output); - break; - - case PARAM_DRC_CONTROL: - __hw_param_copy(&par->drc.control, &cfg->drc.control); - break; - - case PARAM_DRC_OTF_INPUT: - __hw_param_copy(&par->drc.otf_input, &cfg->drc.otf_input); - break; - - case PARAM_DRC_DMA_INPUT: - __hw_param_copy(&par->drc.dma_input, &cfg->drc.dma_input); - break; - - case PARAM_DRC_OTF_OUTPUT: - __hw_param_copy(&par->drc.otf_output, &cfg->drc.otf_output); - break; - - case PARAM_FD_CONTROL: - __hw_param_copy(&par->fd.control, &cfg->fd.control); - break; - - case PARAM_FD_OTF_INPUT: - __hw_param_copy(&par->fd.otf_input, &cfg->fd.otf_input); - break; - - case PARAM_FD_DMA_INPUT: - __hw_param_copy(&par->fd.dma_input, &cfg->fd.dma_input); - break; - - case PARAM_FD_CONFIG: - __hw_param_copy(&par->fd.config, &cfg->fd.config); - break; - - default: - return -EINVAL; - } - - return 0; -} - -unsigned int __get_pending_param_count(struct fimc_is *is) -{ - struct chain_config *config = &is->config[is->config_index]; - unsigned long flags; - unsigned int count; - - spin_lock_irqsave(&is->slock, flags); - count = hweight32(config->p_region_index[0]); - count += hweight32(config->p_region_index[1]); - spin_unlock_irqrestore(&is->slock, flags); - - return count; -} - -int __is_hw_update_params(struct fimc_is *is) -{ - unsigned long *p_index; - int i, id, ret = 0; - - id = is->config_index; - p_index = &is->config[id].p_region_index[0]; - - if (test_bit(PARAM_GLOBAL_SHOTMODE, p_index)) - __fimc_is_hw_update_param_global_shotmode(is); - - if (test_bit(PARAM_SENSOR_FRAME_RATE, p_index)) - __fimc_is_hw_update_param_sensor_framerate(is); - - for (i = PARAM_ISP_CONTROL; i < PARAM_DRC_CONTROL; i++) { - if (test_bit(i, p_index)) - ret = __fimc_is_hw_update_param(is, i); - } - - for (i = PARAM_DRC_CONTROL; i < PARAM_SCALERC_CONTROL; i++) { - if (test_bit(i, p_index)) - ret = __fimc_is_hw_update_param(is, i); - } - - for (i = PARAM_FD_CONTROL; i <= PARAM_FD_CONFIG; i++) { - if (test_bit(i, p_index)) - ret = __fimc_is_hw_update_param(is, i); - } - - return ret; -} - -void __is_get_frame_size(struct fimc_is *is, struct v4l2_mbus_framefmt *mf) -{ - struct isp_param *isp; - - isp = &is->config[is->config_index].isp; - mf->width = isp->otf_input.width; - mf->height = isp->otf_input.height; -} - -void __is_set_frame_size(struct fimc_is *is, struct v4l2_mbus_framefmt *mf) -{ - unsigned int index = is->config_index; - struct isp_param *isp; - struct drc_param *drc; - struct fd_param *fd; - - isp = &is->config[index].isp; - drc = &is->config[index].drc; - fd = &is->config[index].fd; - - /* Update isp size info (OTF only) */ - isp->otf_input.width = mf->width; - isp->otf_input.height = mf->height; - isp->otf_output.width = mf->width; - isp->otf_output.height = mf->height; - /* Update drc size info (OTF only) */ - drc->otf_input.width = mf->width; - drc->otf_input.height = mf->height; - drc->otf_output.width = mf->width; - drc->otf_output.height = mf->height; - /* Update fd size info (OTF only) */ - fd->otf_input.width = mf->width; - fd->otf_input.height = mf->height; - - if (test_bit(PARAM_ISP_OTF_INPUT, - &is->config[index].p_region_index[0])) - return; - - /* Update field */ - fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT); - fimc_is_set_param_bit(is, PARAM_ISP_OTF_OUTPUT); - fimc_is_set_param_bit(is, PARAM_DRC_OTF_INPUT); - fimc_is_set_param_bit(is, PARAM_DRC_OTF_OUTPUT); - fimc_is_set_param_bit(is, PARAM_FD_OTF_INPUT); -} - -int fimc_is_hw_get_sensor_max_framerate(struct fimc_is *is) -{ - switch (is->sensor->drvdata->id) { - case FIMC_IS_SENSOR_ID_S5K6A3: - return 30; - default: - return 15; - } -} - -void __is_set_sensor(struct fimc_is *is, int fps) -{ - unsigned int index = is->config_index; - struct sensor_param *sensor; - struct isp_param *isp; - - sensor = &is->config[index].sensor; - isp = &is->config[index].isp; - - if (fps == 0) { - sensor->frame_rate.frame_rate = - fimc_is_hw_get_sensor_max_framerate(is); - isp->otf_input.frametime_min = 0; - isp->otf_input.frametime_max = 66666; - } else { - sensor->frame_rate.frame_rate = fps; - isp->otf_input.frametime_min = 0; - isp->otf_input.frametime_max = (u32)1000000 / fps; - } - - fimc_is_set_param_bit(is, PARAM_SENSOR_FRAME_RATE); - fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT); -} - -static void __maybe_unused __is_set_init_isp_aa(struct fimc_is *is) -{ - struct isp_param *isp; - - isp = &is->config[is->config_index].isp; - - isp->aa.cmd = ISP_AA_COMMAND_START; - isp->aa.target = ISP_AA_TARGET_AF | ISP_AA_TARGET_AE | - ISP_AA_TARGET_AWB; - isp->aa.mode = 0; - isp->aa.scene = 0; - isp->aa.sleep = 0; - isp->aa.face = 0; - isp->aa.touch_x = 0; - isp->aa.touch_y = 0; - isp->aa.manual_af_setting = 0; - isp->aa.err = ISP_AF_ERROR_NONE; - - fimc_is_set_param_bit(is, PARAM_ISP_AA); -} - -void __is_set_isp_flash(struct fimc_is *is, u32 cmd, u32 redeye) -{ - unsigned int index = is->config_index; - struct isp_param *isp = &is->config[index].isp; - - isp->flash.cmd = cmd; - isp->flash.redeye = redeye; - isp->flash.err = ISP_FLASH_ERROR_NONE; - - fimc_is_set_param_bit(is, PARAM_ISP_FLASH); -} - -void __is_set_isp_awb(struct fimc_is *is, u32 cmd, u32 val) -{ - unsigned int index = is->config_index; - struct isp_param *isp; - - isp = &is->config[index].isp; - - isp->awb.cmd = cmd; - isp->awb.illumination = val; - isp->awb.err = ISP_AWB_ERROR_NONE; - - fimc_is_set_param_bit(is, PARAM_ISP_AWB); -} - -void __is_set_isp_effect(struct fimc_is *is, u32 cmd) -{ - unsigned int index = is->config_index; - struct isp_param *isp; - - isp = &is->config[index].isp; - - isp->effect.cmd = cmd; - isp->effect.err = ISP_IMAGE_EFFECT_ERROR_NONE; - - fimc_is_set_param_bit(is, PARAM_ISP_IMAGE_EFFECT); -} - -void __is_set_isp_iso(struct fimc_is *is, u32 cmd, u32 val) -{ - unsigned int index = is->config_index; - struct isp_param *isp; - - isp = &is->config[index].isp; - - isp->iso.cmd = cmd; - isp->iso.value = val; - isp->iso.err = ISP_ISO_ERROR_NONE; - - fimc_is_set_param_bit(is, PARAM_ISP_ISO); -} - -void __is_set_isp_adjust(struct fimc_is *is, u32 cmd, u32 val) -{ - unsigned int index = is->config_index; - unsigned long *p_index; - struct isp_param *isp; - - p_index = &is->config[index].p_region_index[0]; - isp = &is->config[index].isp; - - switch (cmd) { - case ISP_ADJUST_COMMAND_MANUAL_CONTRAST: - isp->adjust.contrast = val; - break; - case ISP_ADJUST_COMMAND_MANUAL_SATURATION: - isp->adjust.saturation = val; - break; - case ISP_ADJUST_COMMAND_MANUAL_SHARPNESS: - isp->adjust.sharpness = val; - break; - case ISP_ADJUST_COMMAND_MANUAL_EXPOSURE: - isp->adjust.exposure = val; - break; - case ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS: - isp->adjust.brightness = val; - break; - case ISP_ADJUST_COMMAND_MANUAL_HUE: - isp->adjust.hue = val; - break; - case ISP_ADJUST_COMMAND_AUTO: - isp->adjust.contrast = 0; - isp->adjust.saturation = 0; - isp->adjust.sharpness = 0; - isp->adjust.exposure = 0; - isp->adjust.brightness = 0; - isp->adjust.hue = 0; - break; - } - - if (!test_bit(PARAM_ISP_ADJUST, p_index)) { - isp->adjust.cmd = cmd; - isp->adjust.err = ISP_ADJUST_ERROR_NONE; - fimc_is_set_param_bit(is, PARAM_ISP_ADJUST); - } else { - isp->adjust.cmd |= cmd; - } -} - -void __is_set_isp_metering(struct fimc_is *is, u32 id, u32 val) -{ - unsigned int index = is->config_index; - struct isp_param *isp; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[0]; - isp = &is->config[index].isp; - - switch (id) { - case IS_METERING_CONFIG_CMD: - isp->metering.cmd = val; - break; - case IS_METERING_CONFIG_WIN_POS_X: - isp->metering.win_pos_x = val; - break; - case IS_METERING_CONFIG_WIN_POS_Y: - isp->metering.win_pos_y = val; - break; - case IS_METERING_CONFIG_WIN_WIDTH: - isp->metering.win_width = val; - break; - case IS_METERING_CONFIG_WIN_HEIGHT: - isp->metering.win_height = val; - break; - default: - return; - } - - if (!test_bit(PARAM_ISP_METERING, p_index)) { - isp->metering.err = ISP_METERING_ERROR_NONE; - fimc_is_set_param_bit(is, PARAM_ISP_METERING); - } -} - -void __is_set_isp_afc(struct fimc_is *is, u32 cmd, u32 val) -{ - unsigned int index = is->config_index; - struct isp_param *isp; - - isp = &is->config[index].isp; - - isp->afc.cmd = cmd; - isp->afc.manual = val; - isp->afc.err = ISP_AFC_ERROR_NONE; - - fimc_is_set_param_bit(is, PARAM_ISP_AFC); -} - -void __is_set_drc_control(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct drc_param *drc; - - drc = &is->config[index].drc; - - drc->control.bypass = val; - - fimc_is_set_param_bit(is, PARAM_DRC_CONTROL); -} - -void __is_set_fd_control(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct fd_param *fd; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[1]; - fd = &is->config[index].fd; - - fd->control.cmd = val; - - if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) - fimc_is_set_param_bit(is, PARAM_FD_CONTROL); -} - -void __is_set_fd_config_maxface(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct fd_param *fd; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[1]; - fd = &is->config[index].fd; - - fd->config.max_number = val; - - if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) { - fd->config.cmd = FD_CONFIG_COMMAND_MAXIMUM_NUMBER; - fd->config.err = ERROR_FD_NONE; - fimc_is_set_param_bit(is, PARAM_FD_CONFIG); - } else { - fd->config.cmd |= FD_CONFIG_COMMAND_MAXIMUM_NUMBER; - } -} - -void __is_set_fd_config_rollangle(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct fd_param *fd; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[1]; - fd = &is->config[index].fd; - - fd->config.roll_angle = val; - - if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) { - fd->config.cmd = FD_CONFIG_COMMAND_ROLL_ANGLE; - fd->config.err = ERROR_FD_NONE; - fimc_is_set_param_bit(is, PARAM_FD_CONFIG); - } else { - fd->config.cmd |= FD_CONFIG_COMMAND_ROLL_ANGLE; - } -} - -void __is_set_fd_config_yawangle(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct fd_param *fd; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[1]; - fd = &is->config[index].fd; - - fd->config.yaw_angle = val; - - if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) { - fd->config.cmd = FD_CONFIG_COMMAND_YAW_ANGLE; - fd->config.err = ERROR_FD_NONE; - fimc_is_set_param_bit(is, PARAM_FD_CONFIG); - } else { - fd->config.cmd |= FD_CONFIG_COMMAND_YAW_ANGLE; - } -} - -void __is_set_fd_config_smilemode(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct fd_param *fd; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[1]; - fd = &is->config[index].fd; - - fd->config.smile_mode = val; - - if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) { - fd->config.cmd = FD_CONFIG_COMMAND_SMILE_MODE; - fd->config.err = ERROR_FD_NONE; - fimc_is_set_param_bit(is, PARAM_FD_CONFIG); - } else { - fd->config.cmd |= FD_CONFIG_COMMAND_SMILE_MODE; - } -} - -void __is_set_fd_config_blinkmode(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct fd_param *fd; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[1]; - fd = &is->config[index].fd; - - fd->config.blink_mode = val; - - if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) { - fd->config.cmd = FD_CONFIG_COMMAND_BLINK_MODE; - fd->config.err = ERROR_FD_NONE; - fimc_is_set_param_bit(is, PARAM_FD_CONFIG); - } else { - fd->config.cmd |= FD_CONFIG_COMMAND_BLINK_MODE; - } -} - -void __is_set_fd_config_eyedetect(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct fd_param *fd; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[1]; - fd = &is->config[index].fd; - - fd->config.eye_detect = val; - - if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) { - fd->config.cmd = FD_CONFIG_COMMAND_EYES_DETECT; - fd->config.err = ERROR_FD_NONE; - fimc_is_set_param_bit(is, PARAM_FD_CONFIG); - } else { - fd->config.cmd |= FD_CONFIG_COMMAND_EYES_DETECT; - } -} - -void __is_set_fd_config_mouthdetect(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct fd_param *fd; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[1]; - fd = &is->config[index].fd; - - fd->config.mouth_detect = val; - - if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) { - fd->config.cmd = FD_CONFIG_COMMAND_MOUTH_DETECT; - fd->config.err = ERROR_FD_NONE; - fimc_is_set_param_bit(is, PARAM_FD_CONFIG); - } else { - fd->config.cmd |= FD_CONFIG_COMMAND_MOUTH_DETECT; - } -} - -void __is_set_fd_config_orientation(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct fd_param *fd; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[1]; - fd = &is->config[index].fd; - - fd->config.orientation = val; - - if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) { - fd->config.cmd = FD_CONFIG_COMMAND_ORIENTATION; - fd->config.err = ERROR_FD_NONE; - fimc_is_set_param_bit(is, PARAM_FD_CONFIG); - } else { - fd->config.cmd |= FD_CONFIG_COMMAND_ORIENTATION; - } -} - -void __is_set_fd_config_orientation_val(struct fimc_is *is, u32 val) -{ - unsigned int index = is->config_index; - struct fd_param *fd; - unsigned long *p_index; - - p_index = &is->config[index].p_region_index[1]; - fd = &is->config[index].fd; - - fd->config.orientation_value = val; - - if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) { - fd->config.cmd = FD_CONFIG_COMMAND_ORIENTATION_VALUE; - fd->config.err = ERROR_FD_NONE; - fimc_is_set_param_bit(is, PARAM_FD_CONFIG); - } else { - fd->config.cmd |= FD_CONFIG_COMMAND_ORIENTATION_VALUE; - } -} - -void fimc_is_set_initial_params(struct fimc_is *is) -{ - struct global_param *global; - struct isp_param *isp; - struct drc_param *drc; - struct fd_param *fd; - unsigned long *p_index; - unsigned int index; - - index = is->config_index; - global = &is->config[index].global; - isp = &is->config[index].isp; - drc = &is->config[index].drc; - fd = &is->config[index].fd; - p_index = &is->config[index].p_region_index[0]; - - /* Global */ - global->shotmode.cmd = 1; - fimc_is_set_param_bit(is, PARAM_GLOBAL_SHOTMODE); - - /* ISP */ - isp->control.cmd = CONTROL_COMMAND_START; - isp->control.bypass = CONTROL_BYPASS_DISABLE; - isp->control.err = CONTROL_ERROR_NONE; - fimc_is_set_param_bit(is, PARAM_ISP_CONTROL); - - isp->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_ISP_OTF_INPUT, p_index)) { - isp->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH; - isp->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT; - fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT); - } - if (is->sensor->test_pattern) - isp->otf_input.format = OTF_INPUT_FORMAT_STRGEN_COLORBAR_BAYER; - else - isp->otf_input.format = OTF_INPUT_FORMAT_BAYER; - isp->otf_input.bitwidth = 10; - isp->otf_input.order = OTF_INPUT_ORDER_BAYER_GR_BG; - isp->otf_input.crop_offset_x = 0; - isp->otf_input.crop_offset_y = 0; - isp->otf_input.err = OTF_INPUT_ERROR_NONE; - - isp->dma1_input.cmd = DMA_INPUT_COMMAND_DISABLE; - isp->dma1_input.width = 0; - isp->dma1_input.height = 0; - isp->dma1_input.format = 0; - isp->dma1_input.bitwidth = 0; - isp->dma1_input.plane = 0; - isp->dma1_input.order = 0; - isp->dma1_input.buffer_number = 0; - isp->dma1_input.width = 0; - isp->dma1_input.err = DMA_INPUT_ERROR_NONE; - fimc_is_set_param_bit(is, PARAM_ISP_DMA1_INPUT); - - isp->dma2_input.cmd = DMA_INPUT_COMMAND_DISABLE; - isp->dma2_input.width = 0; - isp->dma2_input.height = 0; - isp->dma2_input.format = 0; - isp->dma2_input.bitwidth = 0; - isp->dma2_input.plane = 0; - isp->dma2_input.order = 0; - isp->dma2_input.buffer_number = 0; - isp->dma2_input.width = 0; - isp->dma2_input.err = DMA_INPUT_ERROR_NONE; - fimc_is_set_param_bit(is, PARAM_ISP_DMA2_INPUT); - - isp->aa.cmd = ISP_AA_COMMAND_START; - isp->aa.target = ISP_AA_TARGET_AE | ISP_AA_TARGET_AWB; - fimc_is_set_param_bit(is, PARAM_ISP_AA); - - if (!test_bit(PARAM_ISP_FLASH, p_index)) - __is_set_isp_flash(is, ISP_FLASH_COMMAND_DISABLE, - ISP_FLASH_REDEYE_DISABLE); - - if (!test_bit(PARAM_ISP_AWB, p_index)) - __is_set_isp_awb(is, ISP_AWB_COMMAND_AUTO, 0); - - if (!test_bit(PARAM_ISP_IMAGE_EFFECT, p_index)) - __is_set_isp_effect(is, ISP_IMAGE_EFFECT_DISABLE); - - if (!test_bit(PARAM_ISP_ISO, p_index)) - __is_set_isp_iso(is, ISP_ISO_COMMAND_AUTO, 0); - - if (!test_bit(PARAM_ISP_ADJUST, p_index)) { - __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_CONTRAST, 0); - __is_set_isp_adjust(is, - ISP_ADJUST_COMMAND_MANUAL_SATURATION, 0); - __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_SHARPNESS, 0); - __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_EXPOSURE, 0); - __is_set_isp_adjust(is, - ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS, 0); - __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_HUE, 0); - } - - if (!test_bit(PARAM_ISP_METERING, p_index)) { - __is_set_isp_metering(is, 0, ISP_METERING_COMMAND_CENTER); - __is_set_isp_metering(is, 1, 0); - __is_set_isp_metering(is, 2, 0); - __is_set_isp_metering(is, 3, 0); - __is_set_isp_metering(is, 4, 0); - } - - if (!test_bit(PARAM_ISP_AFC, p_index)) - __is_set_isp_afc(is, ISP_AFC_COMMAND_AUTO, 0); - - isp->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_ISP_OTF_OUTPUT, p_index)) { - isp->otf_output.width = DEFAULT_PREVIEW_STILL_WIDTH; - isp->otf_output.height = DEFAULT_PREVIEW_STILL_HEIGHT; - fimc_is_set_param_bit(is, PARAM_ISP_OTF_OUTPUT); - } - isp->otf_output.format = OTF_OUTPUT_FORMAT_YUV444; - isp->otf_output.bitwidth = 12; - isp->otf_output.order = 0; - isp->otf_output.err = OTF_OUTPUT_ERROR_NONE; - - if (!test_bit(PARAM_ISP_DMA1_OUTPUT, p_index)) { - isp->dma1_output.cmd = DMA_OUTPUT_COMMAND_DISABLE; - isp->dma1_output.width = 0; - isp->dma1_output.height = 0; - isp->dma1_output.format = 0; - isp->dma1_output.bitwidth = 0; - isp->dma1_output.plane = 0; - isp->dma1_output.order = 0; - isp->dma1_output.buffer_number = 0; - isp->dma1_output.buffer_address = 0; - isp->dma1_output.notify_dma_done = 0; - isp->dma1_output.dma_out_mask = 0; - isp->dma1_output.err = DMA_OUTPUT_ERROR_NONE; - fimc_is_set_param_bit(is, PARAM_ISP_DMA1_OUTPUT); - } - - if (!test_bit(PARAM_ISP_DMA2_OUTPUT, p_index)) { - isp->dma2_output.cmd = DMA_OUTPUT_COMMAND_DISABLE; - isp->dma2_output.width = 0; - isp->dma2_output.height = 0; - isp->dma2_output.format = 0; - isp->dma2_output.bitwidth = 0; - isp->dma2_output.plane = 0; - isp->dma2_output.order = 0; - isp->dma2_output.buffer_number = 0; - isp->dma2_output.buffer_address = 0; - isp->dma2_output.notify_dma_done = 0; - isp->dma2_output.dma_out_mask = 0; - isp->dma2_output.err = DMA_OUTPUT_ERROR_NONE; - fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT); - } - - /* Sensor */ - if (!test_bit(PARAM_SENSOR_FRAME_RATE, p_index)) { - if (is->config_index == 0) - __is_set_sensor(is, 0); - } - - /* DRC */ - drc->control.cmd = CONTROL_COMMAND_START; - __is_set_drc_control(is, CONTROL_BYPASS_ENABLE); - - drc->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_DRC_OTF_INPUT, p_index)) { - drc->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH; - drc->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT; - fimc_is_set_param_bit(is, PARAM_DRC_OTF_INPUT); - } - drc->otf_input.format = OTF_INPUT_FORMAT_YUV444; - drc->otf_input.bitwidth = 12; - drc->otf_input.order = 0; - drc->otf_input.err = OTF_INPUT_ERROR_NONE; - - drc->dma_input.cmd = DMA_INPUT_COMMAND_DISABLE; - drc->dma_input.width = 0; - drc->dma_input.height = 0; - drc->dma_input.format = 0; - drc->dma_input.bitwidth = 0; - drc->dma_input.plane = 0; - drc->dma_input.order = 0; - drc->dma_input.buffer_number = 0; - drc->dma_input.width = 0; - drc->dma_input.err = DMA_INPUT_ERROR_NONE; - fimc_is_set_param_bit(is, PARAM_DRC_DMA_INPUT); - - drc->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_DRC_OTF_OUTPUT, p_index)) { - drc->otf_output.width = DEFAULT_PREVIEW_STILL_WIDTH; - drc->otf_output.height = DEFAULT_PREVIEW_STILL_HEIGHT; - fimc_is_set_param_bit(is, PARAM_DRC_OTF_OUTPUT); - } - drc->otf_output.format = OTF_OUTPUT_FORMAT_YUV444; - drc->otf_output.bitwidth = 8; - drc->otf_output.order = 0; - drc->otf_output.err = OTF_OUTPUT_ERROR_NONE; - - /* FD */ - __is_set_fd_control(is, CONTROL_COMMAND_STOP); - fd->control.bypass = CONTROL_BYPASS_DISABLE; - - fd->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_FD_OTF_INPUT, p_index)) { - fd->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH; - fd->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT; - fimc_is_set_param_bit(is, PARAM_FD_OTF_INPUT); - } - - fd->otf_input.format = OTF_INPUT_FORMAT_YUV444; - fd->otf_input.bitwidth = 8; - fd->otf_input.order = 0; - fd->otf_input.err = OTF_INPUT_ERROR_NONE; - - fd->dma_input.cmd = DMA_INPUT_COMMAND_DISABLE; - fd->dma_input.width = 0; - fd->dma_input.height = 0; - fd->dma_input.format = 0; - fd->dma_input.bitwidth = 0; - fd->dma_input.plane = 0; - fd->dma_input.order = 0; - fd->dma_input.buffer_number = 0; - fd->dma_input.width = 0; - fd->dma_input.err = DMA_INPUT_ERROR_NONE; - fimc_is_set_param_bit(is, PARAM_FD_DMA_INPUT); - - __is_set_fd_config_maxface(is, 5); - __is_set_fd_config_rollangle(is, FD_CONFIG_ROLL_ANGLE_FULL); - __is_set_fd_config_yawangle(is, FD_CONFIG_YAW_ANGLE_45_90); - __is_set_fd_config_smilemode(is, FD_CONFIG_SMILE_MODE_DISABLE); - __is_set_fd_config_blinkmode(is, FD_CONFIG_BLINK_MODE_DISABLE); - __is_set_fd_config_eyedetect(is, FD_CONFIG_EYES_DETECT_ENABLE); - __is_set_fd_config_mouthdetect(is, FD_CONFIG_MOUTH_DETECT_DISABLE); - __is_set_fd_config_orientation(is, FD_CONFIG_ORIENTATION_DISABLE); - __is_set_fd_config_orientation_val(is, 0); -} diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.h b/drivers/media/platform/exynos4-is/fimc-is-param.h deleted file mode 100644 index 206904674927..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-param.h +++ /dev/null @@ -1,1022 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. - * - * Authors: Younghwan Joo <yhwan.joo@samsung.com> - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ -#ifndef FIMC_IS_PARAM_H_ -#define FIMC_IS_PARAM_H_ - -#include <linux/compiler.h> - -#define FIMC_IS_CONFIG_TIMEOUT 3000 /* ms */ -#define IS_DEFAULT_WIDTH 1280 -#define IS_DEFAULT_HEIGHT 720 - -#define DEFAULT_PREVIEW_STILL_WIDTH IS_DEFAULT_WIDTH -#define DEFAULT_PREVIEW_STILL_HEIGHT IS_DEFAULT_HEIGHT -#define DEFAULT_CAPTURE_STILL_WIDTH IS_DEFAULT_WIDTH -#define DEFAULT_CAPTURE_STILL_HEIGHT IS_DEFAULT_HEIGHT -#define DEFAULT_PREVIEW_VIDEO_WIDTH IS_DEFAULT_WIDTH -#define DEFAULT_PREVIEW_VIDEO_HEIGHT IS_DEFAULT_HEIGHT -#define DEFAULT_CAPTURE_VIDEO_WIDTH IS_DEFAULT_WIDTH -#define DEFAULT_CAPTURE_VIDEO_HEIGHT IS_DEFAULT_HEIGHT - -#define DEFAULT_PREVIEW_STILL_FRAMERATE 30 -#define DEFAULT_CAPTURE_STILL_FRAMERATE 15 -#define DEFAULT_PREVIEW_VIDEO_FRAMERATE 30 -#define DEFAULT_CAPTURE_VIDEO_FRAMERATE 30 - -#define FIMC_IS_REGION_VER 124 /* IS REGION VERSION 1.24 */ -#define FIMC_IS_PARAM_SIZE (FIMC_IS_REGION_SIZE + 1) -#define FIMC_IS_MAGIC_NUMBER 0x01020304 -#define FIMC_IS_PARAM_MAX_SIZE 64 /* in bytes */ -#define FIMC_IS_PARAM_MAX_ENTRIES (FIMC_IS_PARAM_MAX_SIZE / 4) - -/* The parameter bitmask bit definitions. */ -enum is_param_bit { - PARAM_GLOBAL_SHOTMODE, - PARAM_SENSOR_CONTROL, - PARAM_SENSOR_OTF_OUTPUT, - PARAM_SENSOR_FRAME_RATE, - PARAM_BUFFER_CONTROL, - PARAM_BUFFER_OTF_INPUT, - PARAM_BUFFER_OTF_OUTPUT, - PARAM_ISP_CONTROL, - PARAM_ISP_OTF_INPUT, - PARAM_ISP_DMA1_INPUT, - /* 10 */ - PARAM_ISP_DMA2_INPUT, - PARAM_ISP_AA, - PARAM_ISP_FLASH, - PARAM_ISP_AWB, - PARAM_ISP_IMAGE_EFFECT, - PARAM_ISP_ISO, - PARAM_ISP_ADJUST, - PARAM_ISP_METERING, - PARAM_ISP_AFC, - PARAM_ISP_OTF_OUTPUT, - /* 20 */ - PARAM_ISP_DMA1_OUTPUT, - PARAM_ISP_DMA2_OUTPUT, - PARAM_DRC_CONTROL, - PARAM_DRC_OTF_INPUT, - PARAM_DRC_DMA_INPUT, - PARAM_DRC_OTF_OUTPUT, - PARAM_SCALERC_CONTROL, - PARAM_SCALERC_OTF_INPUT, - PARAM_SCALERC_IMAGE_EFFECT, - PARAM_SCALERC_INPUT_CROP, - /* 30 */ - PARAM_SCALERC_OUTPUT_CROP, - PARAM_SCALERC_OTF_OUTPUT, - PARAM_SCALERC_DMA_OUTPUT, - PARAM_ODC_CONTROL, - PARAM_ODC_OTF_INPUT, - PARAM_ODC_OTF_OUTPUT, - PARAM_DIS_CONTROL, - PARAM_DIS_OTF_INPUT, - PARAM_DIS_OTF_OUTPUT, - PARAM_TDNR_CONTROL, - /* 40 */ - PARAM_TDNR_OTF_INPUT, - PARAM_TDNR_1ST_FRAME, - PARAM_TDNR_OTF_OUTPUT, - PARAM_TDNR_DMA_OUTPUT, - PARAM_SCALERP_CONTROL, - PARAM_SCALERP_OTF_INPUT, - PARAM_SCALERP_IMAGE_EFFECT, - PARAM_SCALERP_INPUT_CROP, - PARAM_SCALERP_OUTPUT_CROP, - PARAM_SCALERP_ROTATION, - /* 50 */ - PARAM_SCALERP_FLIP, - PARAM_SCALERP_OTF_OUTPUT, - PARAM_SCALERP_DMA_OUTPUT, - PARAM_FD_CONTROL, - PARAM_FD_OTF_INPUT, - PARAM_FD_DMA_INPUT, - PARAM_FD_CONFIG, -}; - -/* Interrupt map */ -#define FIMC_IS_INT_GENERAL 0 -#define FIMC_IS_INT_FRAME_DONE_ISP 1 - -/* Input */ - -#define CONTROL_COMMAND_STOP 0 -#define CONTROL_COMMAND_START 1 - -#define CONTROL_BYPASS_DISABLE 0 -#define CONTROL_BYPASS_ENABLE 1 - -#define CONTROL_ERROR_NONE 0 - -/* OTF (On-The-Fly) input interface commands */ -#define OTF_INPUT_COMMAND_DISABLE 0 -#define OTF_INPUT_COMMAND_ENABLE 1 - -/* OTF input interface color formats */ -enum oft_input_fmt { - OTF_INPUT_FORMAT_BAYER = 0, /* 1 channel */ - OTF_INPUT_FORMAT_YUV444 = 1, /* 3 channels */ - OTF_INPUT_FORMAT_YUV422 = 2, /* 3 channels */ - OTF_INPUT_FORMAT_YUV420 = 3, /* 3 channels */ - OTF_INPUT_FORMAT_STRGEN_COLORBAR_BAYER = 10, - OTF_INPUT_FORMAT_BAYER_DMA = 11, -}; - -#define OTF_INPUT_ORDER_BAYER_GR_BG 0 - -/* OTF input error codes */ -#define OTF_INPUT_ERROR_NONE 0 /* Input setting is done */ - -/* DMA input commands */ -#define DMA_INPUT_COMMAND_DISABLE 0 -#define DMA_INPUT_COMMAND_ENABLE 1 - -/* DMA input color formats */ -enum dma_input_fmt { - DMA_INPUT_FORMAT_BAYER = 0, - DMA_INPUT_FORMAT_YUV444 = 1, - DMA_INPUT_FORMAT_YUV422 = 2, - DMA_INPUT_FORMAT_YUV420 = 3, -}; - -enum dma_input_order { - /* (for DMA_INPUT_PLANE_3) */ - DMA_INPUT_ORDER_NO = 0, - /* (only valid at DMA_INPUT_PLANE_2) */ - DMA_INPUT_ORDER_CBCR = 1, - /* (only valid at DMA_INPUT_PLANE_2) */ - DMA_INPUT_ORDER_CRCB = 2, - /* (only valid at DMA_INPUT_PLANE_1 & DMA_INPUT_FORMAT_YUV444) */ - DMA_INPUT_ORDER_YCBCR = 3, - /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */ - DMA_INPUT_ORDER_YYCBCR = 4, - /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */ - DMA_INPUT_ORDER_YCBYCR = 5, - /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */ - DMA_INPUT_ORDER_YCRYCB = 6, - /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */ - DMA_INPUT_ORDER_CBYCRY = 7, - /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */ - DMA_INPUT_ORDER_CRYCBY = 8, - /* (only valid at DMA_INPUT_FORMAT_BAYER) */ - DMA_INPUT_ORDER_GR_BG = 9 -}; - -#define DMA_INPUT_ERROR_NONE 0 /* DMA input setting - is done */ -/* - * Data output parameter definitions - */ -#define OTF_OUTPUT_CROP_DISABLE 0 -#define OTF_OUTPUT_CROP_ENABLE 1 - -#define OTF_OUTPUT_COMMAND_DISABLE 0 -#define OTF_OUTPUT_COMMAND_ENABLE 1 - -enum otf_output_fmt { - OTF_OUTPUT_FORMAT_YUV444 = 1, - OTF_OUTPUT_FORMAT_YUV422 = 2, - OTF_OUTPUT_FORMAT_YUV420 = 3, - OTF_OUTPUT_FORMAT_RGB = 4, -}; - -#define OTF_OUTPUT_ORDER_BAYER_GR_BG 0 - -#define OTF_OUTPUT_ERROR_NONE 0 /* Output Setting is done */ - -#define DMA_OUTPUT_COMMAND_DISABLE 0 -#define DMA_OUTPUT_COMMAND_ENABLE 1 - -enum dma_output_fmt { - DMA_OUTPUT_FORMAT_BAYER = 0, - DMA_OUTPUT_FORMAT_YUV444 = 1, - DMA_OUTPUT_FORMAT_YUV422 = 2, - DMA_OUTPUT_FORMAT_YUV420 = 3, - DMA_OUTPUT_FORMAT_RGB = 4, -}; - -enum dma_output_order { - DMA_OUTPUT_ORDER_NO = 0, - /* for DMA_OUTPUT_PLANE_3 */ - DMA_OUTPUT_ORDER_CBCR = 1, - /* only valid at DMA_INPUT_PLANE_2) */ - DMA_OUTPUT_ORDER_CRCB = 2, - /* only valid at DMA_OUTPUT_PLANE_2) */ - DMA_OUTPUT_ORDER_YYCBCR = 3, - /* only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_YCBYCR = 4, - /* only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_YCRYCB = 5, - /* only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_CBYCRY = 6, - /* only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_CRYCBY = 7, - /* only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_YCBCR = 8, - /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_CRYCB = 9, - /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_CRCBY = 10, - /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_CBYCR = 11, - /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_YCRCB = 12, - /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_CBCRY = 13, - /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */ - DMA_OUTPUT_ORDER_BGR = 14, - /* only valid at DMA_OUTPUT_FORMAT_RGB */ - DMA_OUTPUT_ORDER_GB_BG = 15 - /* only valid at DMA_OUTPUT_FORMAT_BAYER */ -}; - -/* enum dma_output_notify_dma_done */ -#define DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE 0 -#define DMA_OUTPUT_NOTIFY_DMA_DONE_ENABLE 1 - -/* DMA output error codes */ -#define DMA_OUTPUT_ERROR_NONE 0 /* DMA output setting - is done */ - -/* ---------------------- Global ----------------------------------- */ -#define GLOBAL_SHOTMODE_ERROR_NONE 0 /* shot-mode setting - is done */ -/* 3A lock commands */ -#define ISP_AA_COMMAND_START 0 -#define ISP_AA_COMMAND_STOP 1 - -/* 3A lock target */ -#define ISP_AA_TARGET_AF 1 -#define ISP_AA_TARGET_AE 2 -#define ISP_AA_TARGET_AWB 4 - -enum isp_af_mode { - ISP_AF_MODE_MANUAL = 0, - ISP_AF_MODE_SINGLE = 1, - ISP_AF_MODE_CONTINUOUS = 2, - ISP_AF_MODE_TOUCH = 3, - ISP_AF_MODE_SLEEP = 4, - ISP_AF_MODE_INIT = 5, - ISP_AF_MODE_SET_CENTER_WINDOW = 6, - ISP_AF_MODE_SET_TOUCH_WINDOW = 7 -}; - -/* Face AF commands */ -#define ISP_AF_FACE_DISABLE 0 -#define ISP_AF_FACE_ENABLE 1 - -/* AF range */ -#define ISP_AF_RANGE_NORMAL 0 -#define ISP_AF_RANGE_MACRO 1 - -/* AF sleep */ -#define ISP_AF_SLEEP_OFF 0 -#define ISP_AF_SLEEP_ON 1 - -/* Continuous AF commands */ -#define ISP_AF_CONTINUOUS_DISABLE 0 -#define ISP_AF_CONTINUOUS_ENABLE 1 - -/* ISP AF error codes */ -#define ISP_AF_ERROR_NONE 0 /* AF mode change is done */ -#define ISP_AF_ERROR_NONE_LOCK_DONE 1 /* AF lock is done */ - -/* Flash commands */ -#define ISP_FLASH_COMMAND_DISABLE 0 -#define ISP_FLASH_COMMAND_MANUAL_ON 1 /* (forced flash) */ -#define ISP_FLASH_COMMAND_AUTO 2 -#define ISP_FLASH_COMMAND_TORCH 3 /* 3 sec */ - -/* Flash red-eye commands */ -#define ISP_FLASH_REDEYE_DISABLE 0 -#define ISP_FLASH_REDEYE_ENABLE 1 - -/* Flash error codes */ -#define ISP_FLASH_ERROR_NONE 0 /* Flash setting is done */ - -/* -------------------------- AWB ------------------------------------ */ -enum isp_awb_command { - ISP_AWB_COMMAND_AUTO = 0, - ISP_AWB_COMMAND_ILLUMINATION = 1, - ISP_AWB_COMMAND_MANUAL = 2 -}; - -enum isp_awb_illumination { - ISP_AWB_ILLUMINATION_DAYLIGHT = 0, - ISP_AWB_ILLUMINATION_CLOUDY = 1, - ISP_AWB_ILLUMINATION_TUNGSTEN = 2, - ISP_AWB_ILLUMINATION_FLUORESCENT = 3 -}; - -/* ISP AWN error codes */ -#define ISP_AWB_ERROR_NONE 0 /* AWB setting is done */ - -/* -------------------------- Effect ----------------------------------- */ -enum isp_imageeffect_command { - ISP_IMAGE_EFFECT_DISABLE = 0, - ISP_IMAGE_EFFECT_MONOCHROME = 1, - ISP_IMAGE_EFFECT_NEGATIVE_MONO = 2, - ISP_IMAGE_EFFECT_NEGATIVE_COLOR = 3, - ISP_IMAGE_EFFECT_SEPIA = 4 -}; - -/* Image effect error codes */ -#define ISP_IMAGE_EFFECT_ERROR_NONE 0 /* Image effect setting - is done */ -/* ISO commands */ -#define ISP_ISO_COMMAND_AUTO 0 -#define ISP_ISO_COMMAND_MANUAL 1 - -/* ISO error codes */ -#define ISP_ISO_ERROR_NONE 0 /* ISO setting is done */ - -/* ISP adjust commands */ -#define ISP_ADJUST_COMMAND_AUTO (0 << 0) -#define ISP_ADJUST_COMMAND_MANUAL_CONTRAST (1 << 0) -#define ISP_ADJUST_COMMAND_MANUAL_SATURATION (1 << 1) -#define ISP_ADJUST_COMMAND_MANUAL_SHARPNESS (1 << 2) -#define ISP_ADJUST_COMMAND_MANUAL_EXPOSURE (1 << 3) -#define ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS (1 << 4) -#define ISP_ADJUST_COMMAND_MANUAL_HUE (1 << 5) -#define ISP_ADJUST_COMMAND_MANUAL_ALL 0x7f - -/* ISP adjustment error codes */ -#define ISP_ADJUST_ERROR_NONE 0 /* Adjust setting is done */ - -/* - * Exposure metering - */ -enum isp_metering_command { - ISP_METERING_COMMAND_AVERAGE = 0, - ISP_METERING_COMMAND_SPOT = 1, - ISP_METERING_COMMAND_MATRIX = 2, - ISP_METERING_COMMAND_CENTER = 3 -}; - -/* ISP metering error codes */ -#define ISP_METERING_ERROR_NONE 0 /* Metering setting is done */ - -/* - * AFC - */ -enum isp_afc_command { - ISP_AFC_COMMAND_DISABLE = 0, - ISP_AFC_COMMAND_AUTO = 1, - ISP_AFC_COMMAND_MANUAL = 2, -}; - -#define ISP_AFC_MANUAL_50HZ 50 -#define ISP_AFC_MANUAL_60HZ 60 - -/* ------------------------ SCENE MODE--------------------------------- */ -enum isp_scene_mode { - ISP_SCENE_NONE = 0, - ISP_SCENE_PORTRAIT = 1, - ISP_SCENE_LANDSCAPE = 2, - ISP_SCENE_SPORTS = 3, - ISP_SCENE_PARTYINDOOR = 4, - ISP_SCENE_BEACHSNOW = 5, - ISP_SCENE_SUNSET = 6, - ISP_SCENE_DAWN = 7, - ISP_SCENE_FALL = 8, - ISP_SCENE_NIGHT = 9, - ISP_SCENE_AGAINSTLIGHTWLIGHT = 10, - ISP_SCENE_AGAINSTLIGHTWOLIGHT = 11, - ISP_SCENE_FIRE = 12, - ISP_SCENE_TEXT = 13, - ISP_SCENE_CANDLE = 14 -}; - -/* AFC error codes */ -#define ISP_AFC_ERROR_NONE 0 /* AFC setting is done */ - -/* ---------------------------- FD ------------------------------------- */ -enum fd_config_command { - FD_CONFIG_COMMAND_MAXIMUM_NUMBER = 0x1, - FD_CONFIG_COMMAND_ROLL_ANGLE = 0x2, - FD_CONFIG_COMMAND_YAW_ANGLE = 0x4, - FD_CONFIG_COMMAND_SMILE_MODE = 0x8, - FD_CONFIG_COMMAND_BLINK_MODE = 0x10, - FD_CONFIG_COMMAND_EYES_DETECT = 0x20, - FD_CONFIG_COMMAND_MOUTH_DETECT = 0x40, - FD_CONFIG_COMMAND_ORIENTATION = 0x80, - FD_CONFIG_COMMAND_ORIENTATION_VALUE = 0x100 -}; - -enum fd_config_roll_angle { - FD_CONFIG_ROLL_ANGLE_BASIC = 0, - FD_CONFIG_ROLL_ANGLE_PRECISE_BASIC = 1, - FD_CONFIG_ROLL_ANGLE_SIDES = 2, - FD_CONFIG_ROLL_ANGLE_PRECISE_SIDES = 3, - FD_CONFIG_ROLL_ANGLE_FULL = 4, - FD_CONFIG_ROLL_ANGLE_PRECISE_FULL = 5, -}; - -enum fd_config_yaw_angle { - FD_CONFIG_YAW_ANGLE_0 = 0, - FD_CONFIG_YAW_ANGLE_45 = 1, - FD_CONFIG_YAW_ANGLE_90 = 2, - FD_CONFIG_YAW_ANGLE_45_90 = 3, -}; - -/* Smile mode configuration */ -#define FD_CONFIG_SMILE_MODE_DISABLE 0 -#define FD_CONFIG_SMILE_MODE_ENABLE 1 - -/* Blink mode configuration */ -#define FD_CONFIG_BLINK_MODE_DISABLE 0 -#define FD_CONFIG_BLINK_MODE_ENABLE 1 - -/* Eyes detection configuration */ -#define FD_CONFIG_EYES_DETECT_DISABLE 0 -#define FD_CONFIG_EYES_DETECT_ENABLE 1 - -/* Mouth detection configuration */ -#define FD_CONFIG_MOUTH_DETECT_DISABLE 0 -#define FD_CONFIG_MOUTH_DETECT_ENABLE 1 - -#define FD_CONFIG_ORIENTATION_DISABLE 0 -#define FD_CONFIG_ORIENTATION_ENABLE 1 - -struct param_control { - u32 cmd; - u32 bypass; - u32 buffer_address; - u32 buffer_size; - u32 skip_frames; /* only valid at ISP */ - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 6]; - u32 err; -}; - -struct param_otf_input { - u32 cmd; - u32 width; - u32 height; - u32 format; - u32 bitwidth; - u32 order; - u32 crop_offset_x; - u32 crop_offset_y; - u32 crop_width; - u32 crop_height; - u32 frametime_min; - u32 frametime_max; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 13]; - u32 err; -}; - -struct param_dma_input { - u32 cmd; - u32 width; - u32 height; - u32 format; - u32 bitwidth; - u32 plane; - u32 order; - u32 buffer_number; - u32 buffer_address; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 10]; - u32 err; -}; - -struct param_otf_output { - u32 cmd; - u32 width; - u32 height; - u32 format; - u32 bitwidth; - u32 order; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 7]; - u32 err; -}; - -struct param_dma_output { - u32 cmd; - u32 width; - u32 height; - u32 format; - u32 bitwidth; - u32 plane; - u32 order; - u32 buffer_number; - u32 buffer_address; - u32 notify_dma_done; - u32 dma_out_mask; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 12]; - u32 err; -}; - -struct param_global_shotmode { - u32 cmd; - u32 skip_frames; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 3]; - u32 err; -}; - -struct param_sensor_framerate { - u32 frame_rate; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 2]; - u32 err; -}; - -struct param_isp_aa { - u32 cmd; - u32 target; - u32 mode; - u32 scene; - u32 sleep; - u32 face; - u32 touch_x; - u32 touch_y; - u32 manual_af_setting; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 10]; - u32 err; -}; - -struct param_isp_flash { - u32 cmd; - u32 redeye; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 3]; - u32 err; -}; - -struct param_isp_awb { - u32 cmd; - u32 illumination; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 3]; - u32 err; -}; - -struct param_isp_imageeffect { - u32 cmd; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 2]; - u32 err; -}; - -struct param_isp_iso { - u32 cmd; - u32 value; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 3]; - u32 err; -}; - -struct param_isp_adjust { - u32 cmd; - s32 contrast; - s32 saturation; - s32 sharpness; - s32 exposure; - s32 brightness; - s32 hue; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 8]; - u32 err; -}; - -struct param_isp_metering { - u32 cmd; - u32 win_pos_x; - u32 win_pos_y; - u32 win_width; - u32 win_height; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 6]; - u32 err; -}; - -struct param_isp_afc { - u32 cmd; - u32 manual; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 3]; - u32 err; -}; - -struct param_scaler_imageeffect { - u32 cmd; - u32 arbitrary_cb; - u32 arbitrary_cr; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 4]; - u32 err; -}; - -struct param_scaler_input_crop { - u32 cmd; - u32 crop_offset_x; - u32 crop_offset_y; - u32 crop_width; - u32 crop_height; - u32 in_width; - u32 in_height; - u32 out_width; - u32 out_height; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 10]; - u32 err; -}; - -struct param_scaler_output_crop { - u32 cmd; - u32 crop_offset_x; - u32 crop_offset_y; - u32 crop_width; - u32 crop_height; - u32 out_format; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 7]; - u32 err; -}; - -struct param_scaler_rotation { - u32 cmd; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 2]; - u32 err; -}; - -struct param_scaler_flip { - u32 cmd; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 2]; - u32 err; -}; - -struct param_3dnr_1stframe { - u32 cmd; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 2]; - u32 err; -}; - -struct param_fd_config { - u32 cmd; - u32 max_number; - u32 roll_angle; - u32 yaw_angle; - u32 smile_mode; - u32 blink_mode; - u32 eye_detect; - u32 mouth_detect; - u32 orientation; - u32 orientation_value; - u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 11]; - u32 err; -}; - -struct global_param { - struct param_global_shotmode shotmode; -}; - -struct sensor_param { - struct param_control control; - struct param_otf_output otf_output; - struct param_sensor_framerate frame_rate; -} __packed; - -struct buffer_param { - struct param_control control; - struct param_otf_input otf_input; - struct param_otf_output otf_output; -} __packed; - -struct isp_param { - struct param_control control; - struct param_otf_input otf_input; - struct param_dma_input dma1_input; - struct param_dma_input dma2_input; - struct param_isp_aa aa; - struct param_isp_flash flash; - struct param_isp_awb awb; - struct param_isp_imageeffect effect; - struct param_isp_iso iso; - struct param_isp_adjust adjust; - struct param_isp_metering metering; - struct param_isp_afc afc; - struct param_otf_output otf_output; - struct param_dma_output dma1_output; - struct param_dma_output dma2_output; -} __packed; - -struct drc_param { - struct param_control control; - struct param_otf_input otf_input; - struct param_dma_input dma_input; - struct param_otf_output otf_output; -} __packed; - -struct scalerc_param { - struct param_control control; - struct param_otf_input otf_input; - struct param_scaler_imageeffect effect; - struct param_scaler_input_crop input_crop; - struct param_scaler_output_crop output_crop; - struct param_otf_output otf_output; - struct param_dma_output dma_output; -} __packed; - -struct odc_param { - struct param_control control; - struct param_otf_input otf_input; - struct param_otf_output otf_output; -} __packed; - -struct dis_param { - struct param_control control; - struct param_otf_output otf_input; - struct param_otf_output otf_output; -} __packed; - -struct tdnr_param { - struct param_control control; - struct param_otf_input otf_input; - struct param_3dnr_1stframe frame; - struct param_otf_output otf_output; - struct param_dma_output dma_output; -} __packed; - -struct scalerp_param { - struct param_control control; - struct param_otf_input otf_input; - struct param_scaler_imageeffect effect; - struct param_scaler_input_crop input_crop; - struct param_scaler_output_crop output_crop; - struct param_scaler_rotation rotation; - struct param_scaler_flip flip; - struct param_otf_output otf_output; - struct param_dma_output dma_output; -} __packed; - -struct fd_param { - struct param_control control; - struct param_otf_input otf_input; - struct param_dma_input dma_input; - struct param_fd_config config; -} __packed; - -struct is_param_region { - struct global_param global; - struct sensor_param sensor; - struct buffer_param buf; - struct isp_param isp; - struct drc_param drc; - struct scalerc_param scalerc; - struct odc_param odc; - struct dis_param dis; - struct tdnr_param tdnr; - struct scalerp_param scalerp; - struct fd_param fd; -} __packed; - -#define NUMBER_OF_GAMMA_CURVE_POINTS 32 - -struct is_tune_sensor { - u32 exposure; - u32 analog_gain; - u32 frame_rate; - u32 actuator_position; -}; - -struct is_tune_gammacurve { - u32 num_pts_x[NUMBER_OF_GAMMA_CURVE_POINTS]; - u32 num_pts_y_r[NUMBER_OF_GAMMA_CURVE_POINTS]; - u32 num_pts_y_g[NUMBER_OF_GAMMA_CURVE_POINTS]; - u32 num_pts_y_b[NUMBER_OF_GAMMA_CURVE_POINTS]; -}; - -struct is_tune_isp { - /* Brightness level: range 0...100, default 7. */ - u32 brightness_level; - /* Contrast level: range -127...127, default 0. */ - s32 contrast_level; - /* Saturation level: range -127...127, default 0. */ - s32 saturation_level; - s32 gamma_level; - struct is_tune_gammacurve gamma_curve[4]; - /* Hue: range -127...127, default 0. */ - s32 hue; - /* Sharpness blur: range -127...127, default 0. */ - s32 sharpness_blur; - /* Despeckle : range -127~127, default : 0 */ - s32 despeckle; - /* Edge color supression: range -127...127, default 0. */ - s32 edge_color_supression; - /* Noise reduction: range -127...127, default 0. */ - s32 noise_reduction; - /* (32 * 4 + 9) * 4 = 548 bytes */ -} __packed; - -struct is_tune_region { - struct is_tune_sensor sensor; - struct is_tune_isp isp; -} __packed; - -struct rational { - u32 num; - u32 den; -}; - -struct srational { - s32 num; - s32 den; -}; - -#define FLASH_FIRED_SHIFT 0 -#define FLASH_NOT_FIRED 0 -#define FLASH_FIRED 1 - -#define FLASH_STROBE_SHIFT 1 -#define FLASH_STROBE_NO_DETECTION 0 -#define FLASH_STROBE_RESERVED 1 -#define FLASH_STROBE_RETURN_LIGHT_NOT_DETECTED 2 -#define FLASH_STROBE_RETURN_LIGHT_DETECTED 3 - -#define FLASH_MODE_SHIFT 3 -#define FLASH_MODE_UNKNOWN 0 -#define FLASH_MODE_COMPULSORY_FLASH_FIRING 1 -#define FLASH_MODE_COMPULSORY_FLASH_SUPPRESSION 2 -#define FLASH_MODE_AUTO_MODE 3 - -#define FLASH_FUNCTION_SHIFT 5 -#define FLASH_FUNCTION_PRESENT 0 -#define FLASH_FUNCTION_NONE 1 - -#define FLASH_RED_EYE_SHIFT 6 -#define FLASH_RED_EYE_DISABLED 0 -#define FLASH_RED_EYE_SUPPORTED 1 - -enum apex_aperture_value { - F1_0 = 0, - F1_4 = 1, - F2_0 = 2, - F2_8 = 3, - F4_0 = 4, - F5_6 = 5, - F8_9 = 6, - F11_0 = 7, - F16_0 = 8, - F22_0 = 9, - F32_0 = 10, -}; - -struct exif_attribute { - struct rational exposure_time; - struct srational shutter_speed; - u32 iso_speed_rating; - u32 flash; - struct srational brightness; -} __packed; - -struct is_frame_header { - u32 valid; - u32 bad_mark; - u32 captured; - u32 frame_number; - struct exif_attribute exif; -} __packed; - -struct is_fd_rect { - u32 offset_x; - u32 offset_y; - u32 width; - u32 height; -}; - -struct is_face_marker { - u32 frame_number; - struct is_fd_rect face; - struct is_fd_rect left_eye; - struct is_fd_rect right_eye; - struct is_fd_rect mouth; - u32 roll_angle; - u32 yaw_angle; - u32 confidence; - s32 smile_level; - s32 blink_level; -} __packed; - -#define MAX_FRAME_COUNT 8 -#define MAX_FRAME_COUNT_PREVIEW 4 -#define MAX_FRAME_COUNT_CAPTURE 1 -#define MAX_FACE_COUNT 16 -#define MAX_SHARED_COUNT 500 - -struct is_region { - struct is_param_region parameter; - struct is_tune_region tune; - struct is_frame_header header[MAX_FRAME_COUNT]; - struct is_face_marker face[MAX_FACE_COUNT]; - u32 shared[MAX_SHARED_COUNT]; -} __packed; - -/* Offset to the ISP DMA2 output buffer address array. */ -#define DMA2_OUTPUT_ADDR_ARRAY_OFFS \ - (offsetof(struct is_region, shared) + 32 * sizeof(u32)) - -struct is_debug_frame_descriptor { - u32 sensor_frame_time; - u32 sensor_exposure_time; - s32 sensor_analog_gain; - /* monitor for AA */ - u32 req_lei; - - u32 next_next_lei_exp; - u32 next_next_lei_a_gain; - u32 next_next_lei_d_gain; - u32 next_next_lei_statlei; - u32 next_next_lei_lei; - - u32 dummy0; -}; - -#define MAX_FRAMEDESCRIPTOR_CONTEXT_NUM (30*20) /* 600 frames */ -#define MAX_VERSION_DISPLAY_BUF 32 - -struct is_share_region { - u32 frame_time; - u32 exposure_time; - s32 analog_gain; - - u32 r_gain; - u32 g_gain; - u32 b_gain; - - u32 af_position; - u32 af_status; - /* 0 : SIRC_ISP_CAMERA_AUTOFOCUSMESSAGE_NOMESSAGE */ - /* 1 : SIRC_ISP_CAMERA_AUTOFOCUSMESSAGE_REACHED */ - /* 2 : SIRC_ISP_CAMERA_AUTOFOCUSMESSAGE_UNABLETOREACH */ - /* 3 : SIRC_ISP_CAMERA_AUTOFOCUSMESSAGE_LOST */ - /* default : unknown */ - u32 af_scene_type; - - u32 frame_descp_onoff_control; - u32 frame_descp_update_done; - u32 frame_descp_idx; - u32 frame_descp_max_idx; - struct is_debug_frame_descriptor - dbg_frame_descp_ctx[MAX_FRAMEDESCRIPTOR_CONTEXT_NUM]; - - u32 chip_id; - u32 chip_rev_no; - u8 isp_fw_ver_no[MAX_VERSION_DISPLAY_BUF]; - u8 isp_fw_ver_date[MAX_VERSION_DISPLAY_BUF]; - u8 sirc_sdk_ver_no[MAX_VERSION_DISPLAY_BUF]; - u8 sirc_sdk_rev_no[MAX_VERSION_DISPLAY_BUF]; - u8 sirc_sdk_rev_date[MAX_VERSION_DISPLAY_BUF]; -} __packed; - -struct is_debug_control { - u32 write_point; /* 0~ 500KB boundary */ - u32 assert_flag; /* 0: Not invoked, 1: Invoked */ - u32 pabort_flag; /* 0: Not invoked, 1: Invoked */ - u32 dabort_flag; /* 0: Not invoked, 1: Invoked */ -}; - -struct sensor_open_extended { - u32 actuator_type; - u32 mclk; - u32 mipi_lane_num; - u32 mipi_speed; - /* Skip setfile loading when fast_open_sensor is not 0 */ - u32 fast_open_sensor; - /* Activating sensor self calibration mode (6A3) */ - u32 self_calibration_mode; - /* This field is to adjust I2c clock based on ACLK200 */ - /* This value is varied in case of rev 0.2 */ - u32 i2c_sclk; -}; - -struct fimc_is; - -int fimc_is_hw_get_sensor_max_framerate(struct fimc_is *is); -int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset); -void fimc_is_set_initial_params(struct fimc_is *is); -unsigned int __get_pending_param_count(struct fimc_is *is); - -int __is_hw_update_params(struct fimc_is *is); -void __is_get_frame_size(struct fimc_is *is, struct v4l2_mbus_framefmt *mf); -void __is_set_frame_size(struct fimc_is *is, struct v4l2_mbus_framefmt *mf); -void __is_set_sensor(struct fimc_is *is, int fps); -void __is_set_isp_aa_ae(struct fimc_is *is); -void __is_set_isp_flash(struct fimc_is *is, u32 cmd, u32 redeye); -void __is_set_isp_awb(struct fimc_is *is, u32 cmd, u32 val); -void __is_set_isp_effect(struct fimc_is *is, u32 cmd); -void __is_set_isp_iso(struct fimc_is *is, u32 cmd, u32 val); -void __is_set_isp_adjust(struct fimc_is *is, u32 cmd, u32 val); -void __is_set_isp_metering(struct fimc_is *is, u32 id, u32 val); -void __is_set_isp_afc(struct fimc_is *is, u32 cmd, u32 val); -void __is_set_drc_control(struct fimc_is *is, u32 val); -void __is_set_fd_control(struct fimc_is *is, u32 val); -void __is_set_fd_config_maxface(struct fimc_is *is, u32 val); -void __is_set_fd_config_rollangle(struct fimc_is *is, u32 val); -void __is_set_fd_config_yawangle(struct fimc_is *is, u32 val); -void __is_set_fd_config_smilemode(struct fimc_is *is, u32 val); -void __is_set_fd_config_blinkmode(struct fimc_is *is, u32 val); -void __is_set_fd_config_eyedetect(struct fimc_is *is, u32 val); -void __is_set_fd_config_mouthdetect(struct fimc_is *is, u32 val); -void __is_set_fd_config_orientation(struct fimc_is *is, u32 val); -void __is_set_fd_config_orientation_val(struct fimc_is *is, u32 val); -void __is_set_isp_aa_af_mode(struct fimc_is *is, int cmd); -void __is_set_isp_aa_af_start_stop(struct fimc_is *is, int cmd); - -#endif diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.c b/drivers/media/platform/exynos4-is/fimc-is-regs.c deleted file mode 100644 index 366e6393817d..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-regs.c +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. - * - * Authors: Younghwan Joo <yhwan.joo@samsung.com> - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ -#include <linux/delay.h> - -#include "fimc-is.h" -#include "fimc-is-command.h" -#include "fimc-is-regs.h" -#include "fimc-is-sensor.h" - -void fimc_is_fw_clear_irq1(struct fimc_is *is, unsigned int nr) -{ - mcuctl_write(1UL << nr, is, MCUCTL_REG_INTCR1); -} - -void fimc_is_fw_clear_irq2(struct fimc_is *is) -{ - u32 cfg = mcuctl_read(is, MCUCTL_REG_INTSR2); - mcuctl_write(cfg, is, MCUCTL_REG_INTCR2); -} - -void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is) -{ - mcuctl_write(INTGR0_INTGD(0), is, MCUCTL_REG_INTGR0); -} - -int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is) -{ - unsigned int timeout = 2000; - u32 cfg, status; - - do { - cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0); - status = INTMSR0_GET_INTMSD(0, cfg); - - if (--timeout == 0) { - dev_warn(&is->pdev->dev, "%s timeout\n", - __func__); - return -ETIMEDOUT; - } - udelay(1); - } while (status != 0); - - return 0; -} - -int fimc_is_hw_set_param(struct fimc_is *is) -{ - struct chain_config *config = &is->config[is->config_index]; - unsigned int param_count = __get_pending_param_count(is); - - fimc_is_hw_wait_intmsr0_intmsd0(is); - - mcuctl_write(HIC_SET_PARAMETER, is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - mcuctl_write(is->config_index, is, MCUCTL_REG_ISSR(2)); - - mcuctl_write(param_count, is, MCUCTL_REG_ISSR(3)); - mcuctl_write(config->p_region_index[0], is, MCUCTL_REG_ISSR(4)); - mcuctl_write(config->p_region_index[1], is, MCUCTL_REG_ISSR(5)); - - fimc_is_hw_set_intgr0_gd0(is); - return 0; -} - -static int __maybe_unused fimc_is_hw_set_tune(struct fimc_is *is) -{ - fimc_is_hw_wait_intmsr0_intmsd0(is); - - mcuctl_write(HIC_SET_TUNE, is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - mcuctl_write(is->h2i_cmd.entry_id, is, MCUCTL_REG_ISSR(2)); - - fimc_is_hw_set_intgr0_gd0(is); - return 0; -} - -#define FIMC_IS_MAX_PARAMS 4 - -int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num_args) -{ - int i; - - if (num_args > FIMC_IS_MAX_PARAMS) - return -EINVAL; - - is->i2h_cmd.num_args = num_args; - - for (i = 0; i < FIMC_IS_MAX_PARAMS; i++) { - if (i < num_args) - is->i2h_cmd.args[i] = mcuctl_read(is, - MCUCTL_REG_ISSR(12 + i)); - else - is->i2h_cmd.args[i] = 0; - } - return 0; -} - -void fimc_is_hw_set_isp_buf_mask(struct fimc_is *is, unsigned int mask) -{ - if (hweight32(mask) == 1) { - dev_err(&is->pdev->dev, "%s(): not enough buffers (mask %#x)\n", - __func__, mask); - return; - } - - if (mcuctl_read(is, MCUCTL_REG_ISSR(23)) != 0) - dev_dbg(&is->pdev->dev, "non-zero DMA buffer mask\n"); - - mcuctl_write(mask, is, MCUCTL_REG_ISSR(23)); -} - -void fimc_is_hw_set_sensor_num(struct fimc_is *is) -{ - pr_debug("setting sensor index to: %d\n", is->sensor_index); - - mcuctl_write(IH_REPLY_DONE, is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - mcuctl_write(IHC_GET_SENSOR_NUM, is, MCUCTL_REG_ISSR(2)); - mcuctl_write(FIMC_IS_SENSORS_NUM, is, MCUCTL_REG_ISSR(3)); -} - -void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index) -{ - if (is->sensor_index != index) - return; - - fimc_is_hw_wait_intmsr0_intmsd0(is); - mcuctl_write(HIC_CLOSE_SENSOR, is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(2)); - fimc_is_hw_set_intgr0_gd0(is); -} - -void fimc_is_hw_get_setfile_addr(struct fimc_is *is) -{ - fimc_is_hw_wait_intmsr0_intmsd0(is); - mcuctl_write(HIC_GET_SET_FILE_ADDR, is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - fimc_is_hw_set_intgr0_gd0(is); -} - -void fimc_is_hw_load_setfile(struct fimc_is *is) -{ - fimc_is_hw_wait_intmsr0_intmsd0(is); - mcuctl_write(HIC_LOAD_SET_FILE, is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - fimc_is_hw_set_intgr0_gd0(is); -} - -int fimc_is_hw_change_mode(struct fimc_is *is) -{ - static const u8 cmd[] = { - HIC_PREVIEW_STILL, HIC_PREVIEW_VIDEO, - HIC_CAPTURE_STILL, HIC_CAPTURE_VIDEO, - }; - - if (WARN_ON(is->config_index >= ARRAY_SIZE(cmd))) - return -EINVAL; - - mcuctl_write(cmd[is->config_index], is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - mcuctl_write(is->setfile.sub_index, is, MCUCTL_REG_ISSR(2)); - fimc_is_hw_set_intgr0_gd0(is); - return 0; -} - -void fimc_is_hw_stream_on(struct fimc_is *is) -{ - fimc_is_hw_wait_intmsr0_intmsd0(is); - mcuctl_write(HIC_STREAM_ON, is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - mcuctl_write(0, is, MCUCTL_REG_ISSR(2)); - fimc_is_hw_set_intgr0_gd0(is); -} - -void fimc_is_hw_stream_off(struct fimc_is *is) -{ - fimc_is_hw_wait_intmsr0_intmsd0(is); - mcuctl_write(HIC_STREAM_OFF, is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - fimc_is_hw_set_intgr0_gd0(is); -} - -void fimc_is_hw_subip_power_off(struct fimc_is *is) -{ - fimc_is_hw_wait_intmsr0_intmsd0(is); - mcuctl_write(HIC_POWER_DOWN, is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - fimc_is_hw_set_intgr0_gd0(is); -} - -int fimc_is_itf_s_param(struct fimc_is *is, bool update) -{ - int ret; - - if (update) - __is_hw_update_params(is); - - fimc_is_mem_barrier(); - - clear_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state); - fimc_is_hw_set_param(is); - ret = fimc_is_wait_event(is, IS_ST_BLOCK_CMD_CLEARED, 1, - FIMC_IS_CONFIG_TIMEOUT); - if (ret < 0) - dev_err(&is->pdev->dev, "%s() timeout\n", __func__); - - return ret; -} - -int fimc_is_itf_mode_change(struct fimc_is *is) -{ - int ret; - - clear_bit(IS_ST_CHANGE_MODE, &is->state); - fimc_is_hw_change_mode(is); - ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1, - FIMC_IS_CONFIG_TIMEOUT); - if (ret < 0) - dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n", - __func__, is->config_index); - return ret; -} diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.h b/drivers/media/platform/exynos4-is/fimc-is-regs.h deleted file mode 100644 index 5d8b01bc84a2..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-regs.h +++ /dev/null @@ -1,161 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * - * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com> - * Younghwan Joo <yhwan.joo@samsung.com> - */ -#ifndef FIMC_IS_REG_H_ -#define FIMC_IS_REG_H_ - -/* WDT_ISP register */ -#define REG_WDT_ISP 0x00170000 - -/* MCUCTL registers base offset */ -#define MCUCTL_BASE 0x00180000 - -/* MCU Controller Register */ -#define MCUCTL_REG_MCUCTRL (MCUCTL_BASE + 0x00) -#define MCUCTRL_MSWRST (1 << 0) - -/* Boot Base Offset Address Register */ -#define MCUCTL_REG_BBOAR (MCUCTL_BASE + 0x04) - -/* Interrupt Generation Register 0 from Host CPU to VIC */ -#define MCUCTL_REG_INTGR0 (MCUCTL_BASE + 0x08) -/* __n = 0...9 */ -#define INTGR0_INTGC(__n) (1 << ((__n) + 16)) -/* __n = 0...5 */ -#define INTGR0_INTGD(__n) (1 << (__n)) - -/* Interrupt Clear Register 0 from Host CPU to VIC */ -#define MCUCTL_REG_INTCR0 (MCUCTL_BASE + 0x0c) -/* __n = 0...9 */ -#define INTCR0_INTGC(__n) (1 << ((__n) + 16)) -/* __n = 0...5 */ -#define INTCR0_INTCD(__n) (1 << ((__n) + 16)) - -/* Interrupt Mask Register 0 from Host CPU to VIC */ -#define MCUCTL_REG_INTMR0 (MCUCTL_BASE + 0x10) -/* __n = 0...9 */ -#define INTMR0_INTMC(__n) (1 << ((__n) + 16)) -/* __n = 0...5 */ -#define INTMR0_INTMD(__n) (1 << (__n)) - -/* Interrupt Status Register 0 from Host CPU to VIC */ -#define MCUCTL_REG_INTSR0 (MCUCTL_BASE + 0x14) -/* __n (bit number) = 0...4 */ -#define INTSR0_GET_INTSD(x, __n) (((x) >> (__n)) & 0x1) -/* __n (bit number) = 0...9 */ -#define INTSR0_GET_INTSC(x, __n) (((x) >> ((__n) + 16)) & 0x1) - -/* Interrupt Mask Status Register 0 from Host CPU to VIC */ -#define MCUCTL_REG_INTMSR0 (MCUCTL_BASE + 0x18) -/* __n (bit number) = 0...4 */ -#define INTMSR0_GET_INTMSD(x, __n) (((x) >> (__n)) & 0x1) -/* __n (bit number) = 0...9 */ -#define INTMSR0_GET_INTMSC(x, __n) (((x) >> ((__n) + 16)) & 0x1) - -/* Interrupt Generation Register 1 from ISP CPU to Host IC */ -#define MCUCTL_REG_INTGR1 (MCUCTL_BASE + 0x1c) -/* __n = 0...9 */ -#define INTGR1_INTGC(__n) (1 << (__n)) - -/* Interrupt Clear Register 1 from ISP CPU to Host IC */ -#define MCUCTL_REG_INTCR1 (MCUCTL_BASE + 0x20) -/* __n = 0...9 */ -#define INTCR1_INTCC(__n) (1 << (__n)) - -/* Interrupt Mask Register 1 from ISP CPU to Host IC */ -#define MCUCTL_REG_INTMR1 (MCUCTL_BASE + 0x24) -/* __n = 0...9 */ -#define INTMR1_INTMC(__n) (1 << (__n)) - -/* Interrupt Status Register 1 from ISP CPU to Host IC */ -#define MCUCTL_REG_INTSR1 (MCUCTL_BASE + 0x28) -/* Interrupt Mask Status Register 1 from ISP CPU to Host IC */ -#define MCUCTL_REG_INTMSR1 (MCUCTL_BASE + 0x2c) - -/* Interrupt Clear Register 2 from ISP BLK's interrupts to Host IC */ -#define MCUCTL_REG_INTCR2 (MCUCTL_BASE + 0x30) -/* __n = 0...5 */ -#define INTCR2_INTCC(__n) (1 << ((__n) + 16)) - -/* Interrupt Mask Register 2 from ISP BLK's interrupts to Host IC */ -#define MCUCTL_REG_INTMR2 (MCUCTL_BASE + 0x34) -/* __n = 0...25 */ -#define INTMR2_INTMCIS(__n) (1 << (__n)) - -/* Interrupt Status Register 2 from ISP BLK's interrupts to Host IC */ -#define MCUCTL_REG_INTSR2 (MCUCTL_BASE + 0x38) -/* Interrupt Mask Status Register 2 from ISP BLK's interrupts to Host IC */ -#define MCUCTL_REG_INTMSR2 (MCUCTL_BASE + 0x3c) - -/* General Purpose Output Control Register (0~17) */ -#define MCUCTL_REG_GPOCTLR (MCUCTL_BASE + 0x40) -/* __n = 0...17 */ -#define GPOCTLR_GPOG(__n) (1 << (__n)) - -/* General Purpose Pad Output Enable Register (0~17) */ -#define MCUCTL_REG_GPOENCTLR (MCUCTL_BASE + 0x44) -/* __n = 0...17 */ -#define GPOENCTLR_GPOEN(__n) (1 << (__n)) - -/* General Purpose Input Control Register (0~17) */ -#define MCUCTL_REG_GPICTLR (MCUCTL_BASE + 0x48) - -/* Shared registers between ISP CPU and the host CPU - ISSRxx */ - -/* ISSR(1): Command Host -> IS */ -/* ISSR(1): Sensor ID for Command, ISSR2...5 = Parameter 1...4 */ - -/* ISSR(10): Reply IS -> Host */ -/* ISSR(11): Sensor ID for Reply, ISSR12...15 = Parameter 1...4 */ - -/* ISSR(20): ISP_FRAME_DONE : SENSOR ID */ -/* ISSR(21): ISP_FRAME_DONE : PARAMETER 1 */ - -/* ISSR(24): SCALERC_FRAME_DONE : SENSOR ID */ -/* ISSR(25): SCALERC_FRAME_DONE : PARAMETER 1 */ - -/* ISSR(28): 3DNR_FRAME_DONE : SENSOR ID */ -/* ISSR(29): 3DNR_FRAME_DONE : PARAMETER 1 */ - -/* ISSR(32): SCALERP_FRAME_DONE : SENSOR ID */ -/* ISSR(33): SCALERP_FRAME_DONE : PARAMETER 1 */ - -/* __n = 0...63 */ -#define MCUCTL_REG_ISSR(__n) (MCUCTL_BASE + 0x80 + ((__n) * 4)) - -/* PMU ISP register offsets */ -#define REG_CMU_RESET_ISP_SYS_PWR_REG 0x1174 -#define REG_CMU_SYSCLK_ISP_SYS_PWR_REG 0x13b8 -#define REG_PMU_ISP_ARM_SYS 0x1050 -#define REG_PMU_ISP_ARM_CONFIGURATION 0x2280 -#define REG_PMU_ISP_ARM_STATUS 0x2284 -#define REG_PMU_ISP_ARM_OPTION 0x2288 - -void fimc_is_fw_clear_irq1(struct fimc_is *is, unsigned int bit); -void fimc_is_fw_clear_irq2(struct fimc_is *is); -int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num); - -void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is); -int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is); -void fimc_is_hw_set_sensor_num(struct fimc_is *is); -void fimc_is_hw_set_isp_buf_mask(struct fimc_is *is, unsigned int mask); -void fimc_is_hw_stream_on(struct fimc_is *is); -void fimc_is_hw_stream_off(struct fimc_is *is); -int fimc_is_hw_set_param(struct fimc_is *is); -int fimc_is_hw_change_mode(struct fimc_is *is); - -void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index); -void fimc_is_hw_get_setfile_addr(struct fimc_is *is); -void fimc_is_hw_load_setfile(struct fimc_is *is); -void fimc_is_hw_subip_power_off(struct fimc_is *is); - -int fimc_is_itf_s_param(struct fimc_is *is, bool update); -int fimc_is_itf_mode_change(struct fimc_is *is); - -#endif /* FIMC_IS_REG_H_ */ diff --git a/drivers/media/platform/exynos4-is/fimc-is-sensor.c b/drivers/media/platform/exynos4-is/fimc-is-sensor.c deleted file mode 100644 index 0e5b9fede4ae..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-sensor.c +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#include "fimc-is-sensor.h" - -static const struct sensor_drv_data s5k6a3_drvdata = { - .id = FIMC_IS_SENSOR_ID_S5K6A3, - .open_timeout = S5K6A3_OPEN_TIMEOUT, -}; - -static const struct of_device_id fimc_is_sensor_of_ids[] = { - { - .compatible = "samsung,s5k6a3", - .data = &s5k6a3_drvdata, - }, - { } -}; - -const struct sensor_drv_data *fimc_is_sensor_get_drvdata( - struct device_node *node) -{ - const struct of_device_id *of_id; - - of_id = of_match_node(fimc_is_sensor_of_ids, node); - return of_id ? of_id->data : NULL; -} diff --git a/drivers/media/platform/exynos4-is/fimc-is-sensor.h b/drivers/media/platform/exynos4-is/fimc-is-sensor.h deleted file mode 100644 index 9aefc63889de..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is-sensor.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * - * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com> - * Younghwan Joo <yhwan.joo@samsung.com> - */ -#ifndef FIMC_IS_SENSOR_H_ -#define FIMC_IS_SENSOR_H_ - -#include <linux/of.h> -#include <linux/types.h> - -#define S5K6A3_OPEN_TIMEOUT 2000 /* ms */ -#define S5K6A3_SENSOR_WIDTH 1392 -#define S5K6A3_SENSOR_HEIGHT 1392 - -enum fimc_is_sensor_id { - FIMC_IS_SENSOR_ID_S5K3H2 = 1, - FIMC_IS_SENSOR_ID_S5K6A3, - FIMC_IS_SENSOR_ID_S5K4E5, - FIMC_IS_SENSOR_ID_S5K3H7, - FIMC_IS_SENSOR_ID_CUSTOM, - FIMC_IS_SENSOR_ID_END -}; - -#define IS_SENSOR_CTRL_BUS_I2C0 0 -#define IS_SENSOR_CTRL_BUS_I2C1 1 - -struct sensor_drv_data { - enum fimc_is_sensor_id id; - /* sensor open timeout in ms */ - unsigned short open_timeout; -}; - -/** - * struct fimc_is_sensor - fimc-is sensor data structure - * @drvdata: a pointer to the sensor's parameters data structure - * @i2c_bus: ISP I2C bus index (0...1) - * @test_pattern: true to enable video test pattern - */ -struct fimc_is_sensor { - const struct sensor_drv_data *drvdata; - unsigned int i2c_bus; - u8 test_pattern; -}; - -const struct sensor_drv_data *fimc_is_sensor_get_drvdata( - struct device_node *node); - -#endif /* FIMC_IS_SENSOR_H_ */ diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c deleted file mode 100644 index e55e411038f4..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ /dev/null @@ -1,986 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * - * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com> - * Younghwan Joo <yhwan.joo@samsung.com> - */ -#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__ - -#include <linux/device.h> -#include <linux/debugfs.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/firmware.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/of_irq.h> -#include <linux/of_address.h> -#include <linux/of_graph.h> -#include <linux/of_platform.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/slab.h> -#include <linux/types.h> -#include <linux/videodev2.h> -#include <media/videobuf2-dma-contig.h> - -#include "media-dev.h" -#include "fimc-is.h" -#include "fimc-is-command.h" -#include "fimc-is-errno.h" -#include "fimc-is-i2c.h" -#include "fimc-is-param.h" -#include "fimc-is-regs.h" - - -static char *fimc_is_clocks[ISS_CLKS_MAX] = { - [ISS_CLK_PPMUISPX] = "ppmuispx", - [ISS_CLK_PPMUISPMX] = "ppmuispmx", - [ISS_CLK_LITE0] = "lite0", - [ISS_CLK_LITE1] = "lite1", - [ISS_CLK_MPLL] = "mpll", - [ISS_CLK_ISP] = "isp", - [ISS_CLK_DRC] = "drc", - [ISS_CLK_FD] = "fd", - [ISS_CLK_MCUISP] = "mcuisp", - [ISS_CLK_GICISP] = "gicisp", - [ISS_CLK_PWM_ISP] = "pwm_isp", - [ISS_CLK_MCUCTL_ISP] = "mcuctl_isp", - [ISS_CLK_UART] = "uart", - [ISS_CLK_ISP_DIV0] = "ispdiv0", - [ISS_CLK_ISP_DIV1] = "ispdiv1", - [ISS_CLK_MCUISP_DIV0] = "mcuispdiv0", - [ISS_CLK_MCUISP_DIV1] = "mcuispdiv1", - [ISS_CLK_ACLK200] = "aclk200", - [ISS_CLK_ACLK200_DIV] = "div_aclk200", - [ISS_CLK_ACLK400MCUISP] = "aclk400mcuisp", - [ISS_CLK_ACLK400MCUISP_DIV] = "div_aclk400mcuisp", -}; - -static void fimc_is_put_clocks(struct fimc_is *is) -{ - int i; - - for (i = 0; i < ISS_CLKS_MAX; i++) { - if (IS_ERR(is->clocks[i])) - continue; - clk_put(is->clocks[i]); - is->clocks[i] = ERR_PTR(-EINVAL); - } -} - -static int fimc_is_get_clocks(struct fimc_is *is) -{ - int i, ret; - - for (i = 0; i < ISS_CLKS_MAX; i++) - is->clocks[i] = ERR_PTR(-EINVAL); - - for (i = 0; i < ISS_CLKS_MAX; i++) { - is->clocks[i] = clk_get(&is->pdev->dev, fimc_is_clocks[i]); - if (IS_ERR(is->clocks[i])) { - ret = PTR_ERR(is->clocks[i]); - goto err; - } - } - - return 0; -err: - fimc_is_put_clocks(is); - dev_err(&is->pdev->dev, "failed to get clock: %s\n", - fimc_is_clocks[i]); - return ret; -} - -static int fimc_is_setup_clocks(struct fimc_is *is) -{ - int ret; - - ret = clk_set_parent(is->clocks[ISS_CLK_ACLK200], - is->clocks[ISS_CLK_ACLK200_DIV]); - if (ret < 0) - return ret; - - ret = clk_set_parent(is->clocks[ISS_CLK_ACLK400MCUISP], - is->clocks[ISS_CLK_ACLK400MCUISP_DIV]); - if (ret < 0) - return ret; - - ret = clk_set_rate(is->clocks[ISS_CLK_ISP_DIV0], ACLK_AXI_FREQUENCY); - if (ret < 0) - return ret; - - ret = clk_set_rate(is->clocks[ISS_CLK_ISP_DIV1], ACLK_AXI_FREQUENCY); - if (ret < 0) - return ret; - - ret = clk_set_rate(is->clocks[ISS_CLK_MCUISP_DIV0], - ATCLK_MCUISP_FREQUENCY); - if (ret < 0) - return ret; - - return clk_set_rate(is->clocks[ISS_CLK_MCUISP_DIV1], - ATCLK_MCUISP_FREQUENCY); -} - -static int fimc_is_enable_clocks(struct fimc_is *is) -{ - int i, ret; - - for (i = 0; i < ISS_GATE_CLKS_MAX; i++) { - if (IS_ERR(is->clocks[i])) - continue; - ret = clk_prepare_enable(is->clocks[i]); - if (ret < 0) { - dev_err(&is->pdev->dev, "clock %s enable failed\n", - fimc_is_clocks[i]); - for (--i; i >= 0; i--) - clk_disable(is->clocks[i]); - return ret; - } - pr_debug("enabled clock: %s\n", fimc_is_clocks[i]); - } - return 0; -} - -static void fimc_is_disable_clocks(struct fimc_is *is) -{ - int i; - - for (i = 0; i < ISS_GATE_CLKS_MAX; i++) { - if (!IS_ERR(is->clocks[i])) { - clk_disable_unprepare(is->clocks[i]); - pr_debug("disabled clock: %s\n", fimc_is_clocks[i]); - } - } -} - -static int fimc_is_parse_sensor_config(struct fimc_is *is, unsigned int index, - struct device_node *node) -{ - struct fimc_is_sensor *sensor = &is->sensor[index]; - struct device_node *ep, *port; - u32 tmp = 0; - int ret; - - sensor->drvdata = fimc_is_sensor_get_drvdata(node); - if (!sensor->drvdata) { - dev_err(&is->pdev->dev, "no driver data found for: %pOF\n", - node); - return -EINVAL; - } - - ep = of_graph_get_next_endpoint(node, NULL); - if (!ep) - return -ENXIO; - - port = of_graph_get_remote_port(ep); - of_node_put(ep); - if (!port) - return -ENXIO; - - /* Use MIPI-CSIS channel id to determine the ISP I2C bus index. */ - ret = of_property_read_u32(port, "reg", &tmp); - if (ret < 0) { - dev_err(&is->pdev->dev, "reg property not found at: %pOF\n", - port); - of_node_put(port); - return ret; - } - - of_node_put(port); - sensor->i2c_bus = tmp - FIMC_INPUT_MIPI_CSI2_0; - return 0; -} - -static int fimc_is_register_subdevs(struct fimc_is *is) -{ - struct device_node *i2c_bus, *child; - int ret, index = 0; - - ret = fimc_isp_subdev_create(&is->isp); - if (ret < 0) - return ret; - - for_each_compatible_node(i2c_bus, NULL, FIMC_IS_I2C_COMPATIBLE) { - for_each_available_child_of_node(i2c_bus, child) { - ret = fimc_is_parse_sensor_config(is, index, child); - - if (ret < 0 || index >= FIMC_IS_SENSORS_NUM) { - of_node_put(child); - return ret; - } - index++; - } - } - return 0; -} - -static int fimc_is_unregister_subdevs(struct fimc_is *is) -{ - fimc_isp_subdev_destroy(&is->isp); - return 0; -} - -static int fimc_is_load_setfile(struct fimc_is *is, char *file_name) -{ - const struct firmware *fw; - void *buf; - int ret; - - ret = request_firmware(&fw, file_name, &is->pdev->dev); - if (ret < 0) { - dev_err(&is->pdev->dev, "firmware request failed (%d)\n", ret); - return ret; - } - buf = is->memory.vaddr + is->setfile.base; - memcpy(buf, fw->data, fw->size); - fimc_is_mem_barrier(); - is->setfile.size = fw->size; - - pr_debug("mem vaddr: %p, setfile buf: %p\n", is->memory.vaddr, buf); - - memcpy(is->fw.setfile_info, - fw->data + fw->size - FIMC_IS_SETFILE_INFO_LEN, - FIMC_IS_SETFILE_INFO_LEN - 1); - - is->fw.setfile_info[FIMC_IS_SETFILE_INFO_LEN - 1] = '\0'; - is->setfile.state = 1; - - pr_debug("FIMC-IS setfile loaded: base: %#x, size: %zu B\n", - is->setfile.base, fw->size); - - release_firmware(fw); - return ret; -} - -int fimc_is_cpu_set_power(struct fimc_is *is, int on) -{ - unsigned int timeout = FIMC_IS_POWER_ON_TIMEOUT; - - if (on) { - /* Disable watchdog */ - mcuctl_write(0, is, REG_WDT_ISP); - - /* Cortex-A5 start address setting */ - mcuctl_write(is->memory.addr, is, MCUCTL_REG_BBOAR); - - /* Enable and start Cortex-A5 */ - pmuisp_write(0x18000, is, REG_PMU_ISP_ARM_OPTION); - pmuisp_write(0x1, is, REG_PMU_ISP_ARM_CONFIGURATION); - } else { - /* A5 power off */ - pmuisp_write(0x10000, is, REG_PMU_ISP_ARM_OPTION); - pmuisp_write(0x0, is, REG_PMU_ISP_ARM_CONFIGURATION); - - while (pmuisp_read(is, REG_PMU_ISP_ARM_STATUS) & 1) { - if (timeout == 0) - return -ETIME; - timeout--; - udelay(1); - } - } - - return 0; -} - -/* Wait until @bit of @is->state is set to @state in the interrupt handler. */ -int fimc_is_wait_event(struct fimc_is *is, unsigned long bit, - unsigned int state, unsigned int timeout) -{ - - int ret = wait_event_timeout(is->irq_queue, - !state ^ test_bit(bit, &is->state), - timeout); - if (ret == 0) { - dev_WARN(&is->pdev->dev, "%s() timed out\n", __func__); - return -ETIME; - } - return 0; -} - -int fimc_is_start_firmware(struct fimc_is *is) -{ - struct device *dev = &is->pdev->dev; - int ret; - - if (is->fw.f_w == NULL) { - dev_err(dev, "firmware is not loaded\n"); - return -EINVAL; - } - - memcpy(is->memory.vaddr, is->fw.f_w->data, is->fw.f_w->size); - wmb(); - - ret = fimc_is_cpu_set_power(is, 1); - if (ret < 0) - return ret; - - ret = fimc_is_wait_event(is, IS_ST_A5_PWR_ON, 1, - msecs_to_jiffies(FIMC_IS_FW_LOAD_TIMEOUT)); - if (ret < 0) - dev_err(dev, "FIMC-IS CPU power on failed\n"); - - return ret; -} - -/* Allocate working memory for the FIMC-IS CPU. */ -static int fimc_is_alloc_cpu_memory(struct fimc_is *is) -{ - struct device *dev = &is->pdev->dev; - - is->memory.vaddr = dma_alloc_coherent(dev, FIMC_IS_CPU_MEM_SIZE, - &is->memory.addr, GFP_KERNEL); - if (is->memory.vaddr == NULL) - return -ENOMEM; - - is->memory.size = FIMC_IS_CPU_MEM_SIZE; - - dev_info(dev, "FIMC-IS CPU memory base: %pad\n", &is->memory.addr); - - if (((u32)is->memory.addr) & FIMC_IS_FW_ADDR_MASK) { - dev_err(dev, "invalid firmware memory alignment: %#x\n", - (u32)is->memory.addr); - dma_free_coherent(dev, is->memory.size, is->memory.vaddr, - is->memory.addr); - return -EIO; - } - - is->is_p_region = (struct is_region *)(is->memory.vaddr + - FIMC_IS_CPU_MEM_SIZE - FIMC_IS_REGION_SIZE); - - is->is_dma_p_region = is->memory.addr + - FIMC_IS_CPU_MEM_SIZE - FIMC_IS_REGION_SIZE; - - is->is_shared_region = (struct is_share_region *)(is->memory.vaddr + - FIMC_IS_SHARED_REGION_OFFSET); - return 0; -} - -static void fimc_is_free_cpu_memory(struct fimc_is *is) -{ - struct device *dev = &is->pdev->dev; - - if (is->memory.vaddr == NULL) - return; - - dma_free_coherent(dev, is->memory.size, is->memory.vaddr, - is->memory.addr); -} - -static void fimc_is_load_firmware(const struct firmware *fw, void *context) -{ - struct fimc_is *is = context; - struct device *dev = &is->pdev->dev; - void *buf; - int ret; - - if (fw == NULL) { - dev_err(dev, "firmware request failed\n"); - return; - } - mutex_lock(&is->lock); - - if (fw->size < FIMC_IS_FW_SIZE_MIN || fw->size > FIMC_IS_FW_SIZE_MAX) { - dev_err(dev, "wrong firmware size: %zu\n", fw->size); - goto done; - } - - is->fw.size = fw->size; - - ret = fimc_is_alloc_cpu_memory(is); - if (ret < 0) { - dev_err(dev, "failed to allocate FIMC-IS CPU memory\n"); - goto done; - } - - memcpy(is->memory.vaddr, fw->data, fw->size); - wmb(); - - /* Read firmware description. */ - buf = (void *)(is->memory.vaddr + fw->size - FIMC_IS_FW_DESC_LEN); - memcpy(&is->fw.info, buf, FIMC_IS_FW_INFO_LEN); - is->fw.info[FIMC_IS_FW_INFO_LEN] = 0; - - buf = (void *)(is->memory.vaddr + fw->size - FIMC_IS_FW_VER_LEN); - memcpy(&is->fw.version, buf, FIMC_IS_FW_VER_LEN); - is->fw.version[FIMC_IS_FW_VER_LEN - 1] = 0; - - is->fw.state = 1; - - dev_info(dev, "loaded firmware: %s, rev. %s\n", - is->fw.info, is->fw.version); - dev_dbg(dev, "FW size: %zu, DMA addr: %pad\n", fw->size, &is->memory.addr); - - is->is_shared_region->chip_id = 0xe4412; - is->is_shared_region->chip_rev_no = 1; - - fimc_is_mem_barrier(); - - /* - * FIXME: The firmware is not being released for now, as it is - * needed around for copying to the IS working memory every - * time before the Cortex-A5 is restarted. - */ - release_firmware(is->fw.f_w); - is->fw.f_w = fw; -done: - mutex_unlock(&is->lock); -} - -static int fimc_is_request_firmware(struct fimc_is *is, const char *fw_name) -{ - return request_firmware_nowait(THIS_MODULE, - FW_ACTION_UEVENT, fw_name, &is->pdev->dev, - GFP_KERNEL, is, fimc_is_load_firmware); -} - -/* General IS interrupt handler */ -static void fimc_is_general_irq_handler(struct fimc_is *is) -{ - is->i2h_cmd.cmd = mcuctl_read(is, MCUCTL_REG_ISSR(10)); - - switch (is->i2h_cmd.cmd) { - case IHC_GET_SENSOR_NUM: - fimc_is_hw_get_params(is, 1); - fimc_is_hw_wait_intmsr0_intmsd0(is); - fimc_is_hw_set_sensor_num(is); - pr_debug("ISP FW version: %#x\n", is->i2h_cmd.args[0]); - break; - case IHC_SET_FACE_MARK: - case IHC_FRAME_DONE: - fimc_is_hw_get_params(is, 2); - break; - case IHC_SET_SHOT_MARK: - case IHC_AA_DONE: - case IH_REPLY_DONE: - fimc_is_hw_get_params(is, 3); - break; - case IH_REPLY_NOT_DONE: - fimc_is_hw_get_params(is, 4); - break; - case IHC_NOT_READY: - break; - default: - pr_info("unknown command: %#x\n", is->i2h_cmd.cmd); - } - - fimc_is_fw_clear_irq1(is, FIMC_IS_INT_GENERAL); - - switch (is->i2h_cmd.cmd) { - case IHC_GET_SENSOR_NUM: - fimc_is_hw_set_intgr0_gd0(is); - set_bit(IS_ST_A5_PWR_ON, &is->state); - break; - - case IHC_SET_SHOT_MARK: - break; - - case IHC_SET_FACE_MARK: - is->fd_header.count = is->i2h_cmd.args[0]; - is->fd_header.index = is->i2h_cmd.args[1]; - is->fd_header.offset = 0; - break; - - case IHC_FRAME_DONE: - break; - - case IHC_AA_DONE: - pr_debug("AA_DONE - %d, %d, %d\n", is->i2h_cmd.args[0], - is->i2h_cmd.args[1], is->i2h_cmd.args[2]); - break; - - case IH_REPLY_DONE: - pr_debug("ISR_DONE: args[0]: %#x\n", is->i2h_cmd.args[0]); - - switch (is->i2h_cmd.args[0]) { - case HIC_PREVIEW_STILL...HIC_CAPTURE_VIDEO: - /* Get CAC margin */ - set_bit(IS_ST_CHANGE_MODE, &is->state); - is->isp.cac_margin_x = is->i2h_cmd.args[1]; - is->isp.cac_margin_y = is->i2h_cmd.args[2]; - pr_debug("CAC margin (x,y): (%d,%d)\n", - is->isp.cac_margin_x, is->isp.cac_margin_y); - break; - - case HIC_STREAM_ON: - clear_bit(IS_ST_STREAM_OFF, &is->state); - set_bit(IS_ST_STREAM_ON, &is->state); - break; - - case HIC_STREAM_OFF: - clear_bit(IS_ST_STREAM_ON, &is->state); - set_bit(IS_ST_STREAM_OFF, &is->state); - break; - - case HIC_SET_PARAMETER: - is->config[is->config_index].p_region_index[0] = 0; - is->config[is->config_index].p_region_index[1] = 0; - set_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state); - pr_debug("HIC_SET_PARAMETER\n"); - break; - - case HIC_GET_PARAMETER: - break; - - case HIC_SET_TUNE: - break; - - case HIC_GET_STATUS: - break; - - case HIC_OPEN_SENSOR: - set_bit(IS_ST_OPEN_SENSOR, &is->state); - pr_debug("data lanes: %d, settle line: %d\n", - is->i2h_cmd.args[2], is->i2h_cmd.args[1]); - break; - - case HIC_CLOSE_SENSOR: - clear_bit(IS_ST_OPEN_SENSOR, &is->state); - is->sensor_index = 0; - break; - - case HIC_MSG_TEST: - pr_debug("config MSG level completed\n"); - break; - - case HIC_POWER_DOWN: - clear_bit(IS_ST_PWR_SUBIP_ON, &is->state); - break; - - case HIC_GET_SET_FILE_ADDR: - is->setfile.base = is->i2h_cmd.args[1]; - set_bit(IS_ST_SETFILE_LOADED, &is->state); - break; - - case HIC_LOAD_SET_FILE: - set_bit(IS_ST_SETFILE_LOADED, &is->state); - break; - } - break; - - case IH_REPLY_NOT_DONE: - pr_err("ISR_NDONE: %d: %#x, %s\n", is->i2h_cmd.args[0], - is->i2h_cmd.args[1], - fimc_is_strerr(is->i2h_cmd.args[1])); - - if (is->i2h_cmd.args[1] & IS_ERROR_TIME_OUT_FLAG) - pr_err("IS_ERROR_TIME_OUT\n"); - - switch (is->i2h_cmd.args[1]) { - case IS_ERROR_SET_PARAMETER: - fimc_is_mem_barrier(); - } - - switch (is->i2h_cmd.args[0]) { - case HIC_SET_PARAMETER: - is->config[is->config_index].p_region_index[0] = 0; - is->config[is->config_index].p_region_index[1] = 0; - set_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state); - break; - } - break; - - case IHC_NOT_READY: - pr_err("IS control sequence error: Not Ready\n"); - break; - } - - wake_up(&is->irq_queue); -} - -static irqreturn_t fimc_is_irq_handler(int irq, void *priv) -{ - struct fimc_is *is = priv; - unsigned long flags; - u32 status; - - spin_lock_irqsave(&is->slock, flags); - status = mcuctl_read(is, MCUCTL_REG_INTSR1); - - if (status & (1UL << FIMC_IS_INT_GENERAL)) - fimc_is_general_irq_handler(is); - - if (status & (1UL << FIMC_IS_INT_FRAME_DONE_ISP)) - fimc_isp_irq_handler(is); - - spin_unlock_irqrestore(&is->slock, flags); - return IRQ_HANDLED; -} - -static int fimc_is_hw_open_sensor(struct fimc_is *is, - struct fimc_is_sensor *sensor) -{ - struct sensor_open_extended *soe = (void *)&is->is_p_region->shared; - - fimc_is_hw_wait_intmsr0_intmsd0(is); - - soe->self_calibration_mode = 1; - soe->actuator_type = 0; - soe->mipi_lane_num = 0; - soe->mclk = 0; - soe->mipi_speed = 0; - soe->fast_open_sensor = 0; - soe->i2c_sclk = 88000000; - - fimc_is_mem_barrier(); - - /* - * Some user space use cases hang up here without this - * empirically chosen delay. - */ - udelay(100); - - mcuctl_write(HIC_OPEN_SENSOR, is, MCUCTL_REG_ISSR(0)); - mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); - mcuctl_write(sensor->drvdata->id, is, MCUCTL_REG_ISSR(2)); - mcuctl_write(sensor->i2c_bus, is, MCUCTL_REG_ISSR(3)); - mcuctl_write(is->is_dma_p_region, is, MCUCTL_REG_ISSR(4)); - - fimc_is_hw_set_intgr0_gd0(is); - - return fimc_is_wait_event(is, IS_ST_OPEN_SENSOR, 1, - sensor->drvdata->open_timeout); -} - - -int fimc_is_hw_initialize(struct fimc_is *is) -{ - static const int config_ids[] = { - IS_SC_PREVIEW_STILL, IS_SC_PREVIEW_VIDEO, - IS_SC_CAPTURE_STILL, IS_SC_CAPTURE_VIDEO - }; - struct device *dev = &is->pdev->dev; - u32 prev_id; - int i, ret; - - /* Sensor initialization. Only one sensor is currently supported. */ - ret = fimc_is_hw_open_sensor(is, &is->sensor[0]); - if (ret < 0) - return ret; - - /* Get the setfile address. */ - fimc_is_hw_get_setfile_addr(is); - - ret = fimc_is_wait_event(is, IS_ST_SETFILE_LOADED, 1, - FIMC_IS_CONFIG_TIMEOUT); - if (ret < 0) { - dev_err(dev, "get setfile address timed out\n"); - return ret; - } - pr_debug("setfile.base: %#x\n", is->setfile.base); - - /* Load the setfile. */ - fimc_is_load_setfile(is, FIMC_IS_SETFILE_6A3); - clear_bit(IS_ST_SETFILE_LOADED, &is->state); - fimc_is_hw_load_setfile(is); - ret = fimc_is_wait_event(is, IS_ST_SETFILE_LOADED, 1, - FIMC_IS_CONFIG_TIMEOUT); - if (ret < 0) { - dev_err(dev, "loading setfile timed out\n"); - return ret; - } - - pr_debug("setfile: base: %#x, size: %d\n", - is->setfile.base, is->setfile.size); - pr_info("FIMC-IS Setfile info: %s\n", is->fw.setfile_info); - - /* Check magic number. */ - if (is->is_p_region->shared[MAX_SHARED_COUNT - 1] != - FIMC_IS_MAGIC_NUMBER) { - dev_err(dev, "magic number error!\n"); - return -EIO; - } - - pr_debug("shared region: %pad, parameter region: %pad\n", - &is->memory.addr + FIMC_IS_SHARED_REGION_OFFSET, - &is->is_dma_p_region); - - is->setfile.sub_index = 0; - - /* Stream off. */ - fimc_is_hw_stream_off(is); - ret = fimc_is_wait_event(is, IS_ST_STREAM_OFF, 1, - FIMC_IS_CONFIG_TIMEOUT); - if (ret < 0) { - dev_err(dev, "stream off timeout\n"); - return ret; - } - - /* Preserve previous mode. */ - prev_id = is->config_index; - - /* Set initial parameter values. */ - for (i = 0; i < ARRAY_SIZE(config_ids); i++) { - is->config_index = config_ids[i]; - fimc_is_set_initial_params(is); - ret = fimc_is_itf_s_param(is, true); - if (ret < 0) { - is->config_index = prev_id; - return ret; - } - } - is->config_index = prev_id; - - set_bit(IS_ST_INIT_DONE, &is->state); - dev_info(dev, "initialization sequence completed (%d)\n", - is->config_index); - return 0; -} - -static int fimc_is_show(struct seq_file *s, void *data) -{ - struct fimc_is *is = s->private; - const u8 *buf = is->memory.vaddr + FIMC_IS_DEBUG_REGION_OFFSET; - - if (is->memory.vaddr == NULL) { - dev_err(&is->pdev->dev, "firmware memory is not initialized\n"); - return -EIO; - } - - seq_printf(s, "%s\n", buf); - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(fimc_is); - -static void fimc_is_debugfs_remove(struct fimc_is *is) -{ - debugfs_remove_recursive(is->debugfs_entry); - is->debugfs_entry = NULL; -} - -static void fimc_is_debugfs_create(struct fimc_is *is) -{ - is->debugfs_entry = debugfs_create_dir("fimc_is", NULL); - - debugfs_create_file("fw_log", S_IRUGO, is->debugfs_entry, is, - &fimc_is_fops); -} - -static int fimc_is_runtime_resume(struct device *dev); -static int fimc_is_runtime_suspend(struct device *dev); - -static int fimc_is_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct fimc_is *is; - struct resource res; - struct device_node *node; - int ret; - - is = devm_kzalloc(&pdev->dev, sizeof(*is), GFP_KERNEL); - if (!is) - return -ENOMEM; - - is->pdev = pdev; - is->isp.pdev = pdev; - - init_waitqueue_head(&is->irq_queue); - spin_lock_init(&is->slock); - mutex_init(&is->lock); - - ret = of_address_to_resource(dev->of_node, 0, &res); - if (ret < 0) - return ret; - - is->regs = devm_ioremap_resource(dev, &res); - if (IS_ERR(is->regs)) - return PTR_ERR(is->regs); - - node = of_get_child_by_name(dev->of_node, "pmu"); - if (!node) - return -ENODEV; - - is->pmu_regs = of_iomap(node, 0); - of_node_put(node); - if (!is->pmu_regs) - return -ENOMEM; - - is->irq = irq_of_parse_and_map(dev->of_node, 0); - if (!is->irq) { - dev_err(dev, "no irq found\n"); - ret = -EINVAL; - goto err_iounmap; - } - - ret = fimc_is_get_clocks(is); - if (ret < 0) - goto err_iounmap; - - platform_set_drvdata(pdev, is); - - ret = request_irq(is->irq, fimc_is_irq_handler, 0, dev_name(dev), is); - if (ret < 0) { - dev_err(dev, "irq request failed\n"); - goto err_clk; - } - pm_runtime_enable(dev); - - if (!pm_runtime_enabled(dev)) { - ret = fimc_is_runtime_resume(dev); - if (ret < 0) - goto err_irq; - } - - ret = pm_runtime_resume_and_get(dev); - if (ret < 0) - goto err_irq; - - vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); - - ret = devm_of_platform_populate(dev); - if (ret < 0) - goto err_pm; - - /* - * Register FIMC-IS V4L2 subdevs to this driver. The video nodes - * will be created within the subdev's registered() callback. - */ - ret = fimc_is_register_subdevs(is); - if (ret < 0) - goto err_pm; - - fimc_is_debugfs_create(is); - - ret = fimc_is_request_firmware(is, FIMC_IS_FW_FILENAME); - if (ret < 0) - goto err_dfs; - - pm_runtime_put_sync(dev); - - dev_dbg(dev, "FIMC-IS registered successfully\n"); - return 0; - -err_dfs: - fimc_is_debugfs_remove(is); - fimc_is_unregister_subdevs(is); -err_pm: - pm_runtime_put_noidle(dev); - if (!pm_runtime_enabled(dev)) - fimc_is_runtime_suspend(dev); -err_irq: - free_irq(is->irq, is); -err_clk: - fimc_is_put_clocks(is); -err_iounmap: - iounmap(is->pmu_regs); - return ret; -} - -static int fimc_is_runtime_resume(struct device *dev) -{ - struct fimc_is *is = dev_get_drvdata(dev); - int ret; - - ret = fimc_is_setup_clocks(is); - if (ret) - return ret; - - return fimc_is_enable_clocks(is); -} - -static int fimc_is_runtime_suspend(struct device *dev) -{ - struct fimc_is *is = dev_get_drvdata(dev); - - fimc_is_disable_clocks(is); - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int fimc_is_resume(struct device *dev) -{ - /* TODO: */ - return 0; -} - -static int fimc_is_suspend(struct device *dev) -{ - struct fimc_is *is = dev_get_drvdata(dev); - - /* TODO: */ - if (test_bit(IS_ST_A5_PWR_ON, &is->state)) - return -EBUSY; - - return 0; -} -#endif /* CONFIG_PM_SLEEP */ - -static int fimc_is_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct fimc_is *is = dev_get_drvdata(dev); - - pm_runtime_disable(dev); - pm_runtime_set_suspended(dev); - if (!pm_runtime_status_suspended(dev)) - fimc_is_runtime_suspend(dev); - free_irq(is->irq, is); - fimc_is_unregister_subdevs(is); - vb2_dma_contig_clear_max_seg_size(dev); - fimc_is_put_clocks(is); - iounmap(is->pmu_regs); - fimc_is_debugfs_remove(is); - release_firmware(is->fw.f_w); - fimc_is_free_cpu_memory(is); - - return 0; -} - -static const struct of_device_id fimc_is_of_match[] = { - { .compatible = "samsung,exynos4212-fimc-is" }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, fimc_is_of_match); - -static const struct dev_pm_ops fimc_is_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(fimc_is_suspend, fimc_is_resume) - SET_RUNTIME_PM_OPS(fimc_is_runtime_suspend, fimc_is_runtime_resume, - NULL) -}; - -static struct platform_driver fimc_is_driver = { - .probe = fimc_is_probe, - .remove = fimc_is_remove, - .driver = { - .of_match_table = fimc_is_of_match, - .name = FIMC_IS_DRV_NAME, - .pm = &fimc_is_pm_ops, - } -}; - -static int fimc_is_module_init(void) -{ - int ret; - - ret = fimc_is_register_i2c_driver(); - if (ret < 0) - return ret; - - ret = platform_driver_register(&fimc_is_driver); - - if (ret < 0) - fimc_is_unregister_i2c_driver(); - - return ret; -} - -static void fimc_is_module_exit(void) -{ - fimc_is_unregister_i2c_driver(); - platform_driver_unregister(&fimc_is_driver); -} - -module_init(fimc_is_module_init); -module_exit(fimc_is_module_exit); - -MODULE_ALIAS("platform:" FIMC_IS_DRV_NAME); -MODULE_AUTHOR("Younghwan Joo <yhwan.joo@samsung.com>"); -MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h deleted file mode 100644 index 06586e455b1d..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-is.h +++ /dev/null @@ -1,359 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * - * Authors: Younghwan Joo <yhwan.joo@samsung.com> - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ -#ifndef FIMC_IS_H_ -#define FIMC_IS_H_ - -#include <asm/barrier.h> -#include <linux/clk.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/pinctrl/consumer.h> -#include <linux/platform_device.h> -#include <linux/sizes.h> -#include <linux/spinlock.h> -#include <linux/types.h> -#include <media/videobuf2-v4l2.h> -#include <media/v4l2-ctrls.h> - -#include "fimc-isp.h" -#include "fimc-is-command.h" -#include "fimc-is-sensor.h" -#include "fimc-is-param.h" -#include "fimc-is-regs.h" - -#define FIMC_IS_DRV_NAME "exynos4-fimc-is" - -#define FIMC_IS_FW_FILENAME "exynos4_fimc_is_fw.bin" -#define FIMC_IS_SETFILE_6A3 "exynos4_s5k6a3_setfile.bin" - -#define FIMC_IS_FW_LOAD_TIMEOUT 1000 /* ms */ -#define FIMC_IS_POWER_ON_TIMEOUT 1000 /* us */ - -#define FIMC_IS_SENSORS_NUM 2 - -/* Memory definitions */ -#define FIMC_IS_CPU_MEM_SIZE (0xa00000) -#define FIMC_IS_CPU_BASE_MASK ((1 << 26) - 1) -#define FIMC_IS_REGION_SIZE 0x5000 - -#define FIMC_IS_DEBUG_REGION_OFFSET 0x0084b000 -#define FIMC_IS_SHARED_REGION_OFFSET 0x008c0000 -#define FIMC_IS_FW_INFO_LEN 31 -#define FIMC_IS_FW_VER_LEN 7 -#define FIMC_IS_FW_DESC_LEN (FIMC_IS_FW_INFO_LEN + \ - FIMC_IS_FW_VER_LEN) -#define FIMC_IS_SETFILE_INFO_LEN 39 - -#define FIMC_IS_EXTRA_MEM_SIZE (FIMC_IS_EXTRA_FW_SIZE + \ - FIMC_IS_EXTRA_SETFILE_SIZE + 0x1000) -#define FIMC_IS_EXTRA_FW_SIZE 0x180000 -#define FIMC_IS_EXTRA_SETFILE_SIZE 0x4b000 - -/* TODO: revisit */ -#define FIMC_IS_FW_ADDR_MASK ((1 << 26) - 1) -#define FIMC_IS_FW_SIZE_MAX (SZ_4M) -#define FIMC_IS_FW_SIZE_MIN (SZ_32K) - -#define ATCLK_MCUISP_FREQUENCY 100000000UL -#define ACLK_AXI_FREQUENCY 100000000UL - -enum { - ISS_CLK_PPMUISPX, - ISS_CLK_PPMUISPMX, - ISS_CLK_LITE0, - ISS_CLK_LITE1, - ISS_CLK_MPLL, - ISS_CLK_ISP, - ISS_CLK_DRC, - ISS_CLK_FD, - ISS_CLK_MCUISP, - ISS_CLK_GICISP, - ISS_CLK_PWM_ISP, - ISS_CLK_MCUCTL_ISP, - ISS_CLK_UART, - ISS_GATE_CLKS_MAX, - ISS_CLK_ISP_DIV0 = ISS_GATE_CLKS_MAX, - ISS_CLK_ISP_DIV1, - ISS_CLK_MCUISP_DIV0, - ISS_CLK_MCUISP_DIV1, - ISS_CLK_ACLK200, - ISS_CLK_ACLK200_DIV, - ISS_CLK_ACLK400MCUISP, - ISS_CLK_ACLK400MCUISP_DIV, - ISS_CLKS_MAX -}; - -/* The driver's internal state flags */ -enum { - IS_ST_IDLE, - IS_ST_PWR_ON, - IS_ST_A5_PWR_ON, - IS_ST_FW_LOADED, - IS_ST_OPEN_SENSOR, - IS_ST_SETFILE_LOADED, - IS_ST_INIT_DONE, - IS_ST_STREAM_ON, - IS_ST_STREAM_OFF, - IS_ST_CHANGE_MODE, - IS_ST_BLOCK_CMD_CLEARED, - IS_ST_SET_ZOOM, - IS_ST_PWR_SUBIP_ON, - IS_ST_END, -}; - -enum af_state { - FIMC_IS_AF_IDLE = 0, - FIMC_IS_AF_SETCONFIG = 1, - FIMC_IS_AF_RUNNING = 2, - FIMC_IS_AF_LOCK = 3, - FIMC_IS_AF_ABORT = 4, - FIMC_IS_AF_FAILED = 5, -}; - -enum af_lock_state { - FIMC_IS_AF_UNLOCKED = 0, - FIMC_IS_AF_LOCKED = 2 -}; - -enum ae_lock_state { - FIMC_IS_AE_UNLOCKED = 0, - FIMC_IS_AE_LOCKED = 1 -}; - -enum awb_lock_state { - FIMC_IS_AWB_UNLOCKED = 0, - FIMC_IS_AWB_LOCKED = 1 -}; - -enum { - IS_METERING_CONFIG_CMD, - IS_METERING_CONFIG_WIN_POS_X, - IS_METERING_CONFIG_WIN_POS_Y, - IS_METERING_CONFIG_WIN_WIDTH, - IS_METERING_CONFIG_WIN_HEIGHT, - IS_METERING_CONFIG_MAX -}; - -struct is_setfile { - const struct firmware *info; - int state; - u32 sub_index; - u32 base; - size_t size; -}; - -struct is_fd_result_header { - u32 offset; - u32 count; - u32 index; - u32 curr_index; - u32 width; - u32 height; -}; - -struct is_af_info { - u16 mode; - u32 af_state; - u32 af_lock_state; - u32 ae_lock_state; - u32 awb_lock_state; - u16 pos_x; - u16 pos_y; - u16 prev_pos_x; - u16 prev_pos_y; - u16 use_af; -}; - -struct fimc_is_firmware { - const struct firmware *f_w; - - dma_addr_t addr; - void *vaddr; - unsigned int size; - - char info[FIMC_IS_FW_INFO_LEN + 1]; - char version[FIMC_IS_FW_VER_LEN + 1]; - char setfile_info[FIMC_IS_SETFILE_INFO_LEN + 1]; - u8 state; -}; - -struct fimc_is_memory { - /* DMA base address */ - dma_addr_t addr; - /* virtual base address */ - void *vaddr; - /* total length */ - unsigned int size; -}; - -#define FIMC_IS_I2H_MAX_ARGS 12 - -struct i2h_cmd { - u32 cmd; - u32 sensor_id; - u16 num_args; - u32 args[FIMC_IS_I2H_MAX_ARGS]; -}; - -struct h2i_cmd { - u16 cmd_type; - u32 entry_id; -}; - -#define FIMC_IS_DEBUG_MSG 0x3f -#define FIMC_IS_DEBUG_LEVEL 3 - -struct fimc_is_setfile { - const struct firmware *info; - unsigned int state; - unsigned int size; - u32 sub_index; - u32 base; -}; - -struct chain_config { - struct global_param global; - struct sensor_param sensor; - struct isp_param isp; - struct drc_param drc; - struct fd_param fd; - - unsigned long p_region_index[2]; -}; - -/** - * struct fimc_is - fimc-is data structure - * @pdev: pointer to FIMC-IS platform device - * @pctrl: pointer to pinctrl structure for this device - * @v4l2_dev: pointer to the top level v4l2_device - * @fw: data structure describing the FIMC-IS firmware binary - * @memory: memory region assigned for the FIMC-IS (firmware) - * @isp: the ISP block data structure - * @sensor: fimc-is sensor subdevice array - * @setfile: descriptor of the imaging pipeline calibration data - * @ctrl_handler: the v4l2 controls handler - * @lock: mutex serializing video device and the subdev operations - * @slock: spinlock protecting this data structure and the hw registers - * @clocks: FIMC-LITE gate clock - * @regs: MCUCTL mmapped registers region - * @pmu_regs: PMU ISP mmapped registers region - * @irq: FIMC-IS interrupt - * @irq_queue: interrupt handling waitqueue - * @lpm: low power mode flag - * @state: internal driver's state flags - * @sensor_index: image sensor index for the firmware - * @i2h_cmd: FIMC-IS to the host (CPU) mailbox command data structure - * @h2i_cmd: the host (CPU) to FIMC-IS mailbox command data structure - * @fd_header: the face detection result data structure - * @config: shared HW pipeline configuration data - * @config_index: index to the @config entry currently in use - * @is_p_region: pointer to the shared parameter memory region - * @is_dma_p_region: DMA address of the shared parameter memory region - * @is_shared_region: pointer to the IS shared region data structure - * @af: auto focus data - * @debugfs_entry: debugfs entry for the firmware log - */ -struct fimc_is { - struct platform_device *pdev; - struct pinctrl *pctrl; - struct v4l2_device *v4l2_dev; - - struct fimc_is_firmware fw; - struct fimc_is_memory memory; - - struct fimc_isp isp; - struct fimc_is_sensor sensor[FIMC_IS_SENSORS_NUM]; - struct fimc_is_setfile setfile; - - struct v4l2_ctrl_handler ctrl_handler; - - struct mutex lock; - spinlock_t slock; - - struct clk *clocks[ISS_CLKS_MAX]; - void __iomem *regs; - void __iomem *pmu_regs; - int irq; - wait_queue_head_t irq_queue; - u8 lpm; - - unsigned long state; - unsigned int sensor_index; - - struct i2h_cmd i2h_cmd; - struct h2i_cmd h2i_cmd; - struct is_fd_result_header fd_header; - - struct chain_config config[IS_SC_MAX]; - unsigned config_index; - - struct is_region *is_p_region; - dma_addr_t is_dma_p_region; - struct is_share_region *is_shared_region; - struct is_af_info af; - - struct dentry *debugfs_entry; -}; - -static inline struct fimc_is *fimc_isp_to_is(struct fimc_isp *isp) -{ - return container_of(isp, struct fimc_is, isp); -} - -static inline struct chain_config *__get_curr_is_config(struct fimc_is *is) -{ - return &is->config[is->config_index]; -} - -static inline void fimc_is_mem_barrier(void) -{ - mb(); -} - -static inline void fimc_is_set_param_bit(struct fimc_is *is, int num) -{ - struct chain_config *cfg = &is->config[is->config_index]; - - set_bit(num, &cfg->p_region_index[0]); -} - -static inline void fimc_is_set_param_ctrl_cmd(struct fimc_is *is, int cmd) -{ - is->is_p_region->parameter.isp.control.cmd = cmd; -} - -static inline void mcuctl_write(u32 v, struct fimc_is *is, unsigned int offset) -{ - writel(v, is->regs + offset); -} - -static inline u32 mcuctl_read(struct fimc_is *is, unsigned int offset) -{ - return readl(is->regs + offset); -} - -static inline void pmuisp_write(u32 v, struct fimc_is *is, unsigned int offset) -{ - writel(v, is->pmu_regs + offset); -} - -static inline u32 pmuisp_read(struct fimc_is *is, unsigned int offset) -{ - return readl(is->pmu_regs + offset); -} - -int fimc_is_wait_event(struct fimc_is *is, unsigned long bit, - unsigned int state, unsigned int timeout); -int fimc_is_cpu_set_power(struct fimc_is *is, int on); -int fimc_is_start_firmware(struct fimc_is *is); -int fimc_is_hw_initialize(struct fimc_is *is); -void fimc_is_log_dump(const char *level, const void *buf, size_t len); - -#endif /* FIMC_IS_H_ */ diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c deleted file mode 100644 index 83688a7982f7..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ /dev/null @@ -1,656 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * FIMC-IS ISP video input and video output DMA interface driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> - * - * The hardware handling code derived from a driver written by - * Younghwan Joo <yhwan.joo@samsung.com>. - */ - -#include <linux/bitops.h> -#include <linux/device.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/printk.h> -#include <linux/pm_runtime.h> -#include <linux/slab.h> -#include <linux/videodev2.h> - -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> -#include <media/videobuf2-v4l2.h> -#include <media/videobuf2-dma-contig.h> -#include <media/drv-intf/exynos-fimc.h> - -#include "common.h" -#include "media-dev.h" -#include "fimc-is.h" -#include "fimc-isp-video.h" -#include "fimc-is-param.h" - -static int isp_video_capture_queue_setup(struct vb2_queue *vq, - unsigned int *num_buffers, unsigned int *num_planes, - unsigned int sizes[], struct device *alloc_devs[]) -{ - struct fimc_isp *isp = vb2_get_drv_priv(vq); - struct v4l2_pix_format_mplane *vid_fmt = &isp->video_capture.pixfmt; - const struct fimc_fmt *fmt = isp->video_capture.format; - unsigned int wh, i; - - wh = vid_fmt->width * vid_fmt->height; - - if (fmt == NULL) - return -EINVAL; - - *num_buffers = clamp_t(u32, *num_buffers, FIMC_ISP_REQ_BUFS_MIN, - FIMC_ISP_REQ_BUFS_MAX); - if (*num_planes) { - if (*num_planes != fmt->memplanes) - return -EINVAL; - for (i = 0; i < *num_planes; i++) - if (sizes[i] < (wh * fmt->depth[i]) / 8) - return -EINVAL; - return 0; - } - - *num_planes = fmt->memplanes; - - for (i = 0; i < fmt->memplanes; i++) - sizes[i] = (wh * fmt->depth[i]) / 8; - - return 0; -} - -static inline struct param_dma_output *__get_isp_dma2(struct fimc_is *is) -{ - return &__get_curr_is_config(is)->isp.dma2_output; -} - -static int isp_video_capture_start_streaming(struct vb2_queue *q, - unsigned int count) -{ - struct fimc_isp *isp = vb2_get_drv_priv(q); - struct fimc_is *is = fimc_isp_to_is(isp); - struct param_dma_output *dma = __get_isp_dma2(is); - struct fimc_is_video *video = &isp->video_capture; - int ret; - - if (!test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state) || - test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state)) - return 0; - - - dma->cmd = DMA_OUTPUT_COMMAND_ENABLE; - dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_ENABLE; - dma->buffer_address = is->is_dma_p_region + - DMA2_OUTPUT_ADDR_ARRAY_OFFS; - dma->buffer_number = video->reqbufs_count; - dma->dma_out_mask = video->buf_mask; - - isp_dbg(2, &video->ve.vdev, - "buf_count: %d, planes: %d, dma addr table: %#x\n", - video->buf_count, video->format->memplanes, - dma->buffer_address); - - fimc_is_mem_barrier(); - - fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT); - __fimc_is_hw_update_param(is, PARAM_ISP_DMA2_OUTPUT); - - ret = fimc_is_itf_s_param(is, false); - if (ret < 0) - return ret; - - ret = fimc_pipeline_call(&video->ve, set_stream, 1); - if (ret < 0) - return ret; - - set_bit(ST_ISP_VID_CAP_STREAMING, &isp->state); - return ret; -} - -static void isp_video_capture_stop_streaming(struct vb2_queue *q) -{ - struct fimc_isp *isp = vb2_get_drv_priv(q); - struct fimc_is *is = fimc_isp_to_is(isp); - struct param_dma_output *dma = __get_isp_dma2(is); - int ret; - - ret = fimc_pipeline_call(&isp->video_capture.ve, set_stream, 0); - if (ret < 0) - return; - - dma->cmd = DMA_OUTPUT_COMMAND_DISABLE; - dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE; - dma->buffer_number = 0; - dma->buffer_address = 0; - dma->dma_out_mask = 0; - - fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT); - __fimc_is_hw_update_param(is, PARAM_ISP_DMA2_OUTPUT); - - ret = fimc_is_itf_s_param(is, false); - if (ret < 0) - dev_warn(&is->pdev->dev, "%s: DMA stop failed\n", __func__); - - fimc_is_hw_set_isp_buf_mask(is, 0); - - clear_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state); - clear_bit(ST_ISP_VID_CAP_STREAMING, &isp->state); - - isp->video_capture.buf_count = 0; -} - -static int isp_video_capture_buffer_prepare(struct vb2_buffer *vb) -{ - struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue); - struct fimc_is_video *video = &isp->video_capture; - int i; - - if (video->format == NULL) - return -EINVAL; - - for (i = 0; i < video->format->memplanes; i++) { - unsigned long size = video->pixfmt.plane_fmt[i].sizeimage; - - if (vb2_plane_size(vb, i) < size) { - v4l2_err(&video->ve.vdev, - "User buffer too small (%ld < %ld)\n", - vb2_plane_size(vb, i), size); - return -EINVAL; - } - vb2_set_plane_payload(vb, i, size); - } - - /* Check if we get one of the already known buffers. */ - if (test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state)) { - dma_addr_t dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); - int i; - - for (i = 0; i < video->buf_count; i++) - if (video->buffers[i]->dma_addr[0] == dma_addr) - return 0; - return -ENXIO; - } - - return 0; -} - -static void isp_video_capture_buffer_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue); - struct fimc_is_video *video = &isp->video_capture; - struct fimc_is *is = fimc_isp_to_is(isp); - struct isp_video_buf *ivb = to_isp_video_buf(vbuf); - unsigned long flags; - unsigned int i; - - if (test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state)) { - spin_lock_irqsave(&is->slock, flags); - video->buf_mask |= BIT(ivb->index); - spin_unlock_irqrestore(&is->slock, flags); - } else { - unsigned int num_planes = video->format->memplanes; - - ivb->index = video->buf_count; - video->buffers[ivb->index] = ivb; - - for (i = 0; i < num_planes; i++) { - int buf_index = ivb->index * num_planes + i; - - ivb->dma_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); - is->is_p_region->shared[32 + buf_index] = - ivb->dma_addr[i]; - - isp_dbg(2, &video->ve.vdev, - "dma_buf %d (%d/%d/%d) addr: %pad\n", - buf_index, ivb->index, i, vb->index, - &ivb->dma_addr[i]); - } - - if (++video->buf_count < video->reqbufs_count) - return; - - video->buf_mask = (1UL << video->buf_count) - 1; - set_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state); - } - - if (!test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state)) - isp_video_capture_start_streaming(vb->vb2_queue, 0); -} - -/* - * FIMC-IS ISP input and output DMA interface interrupt handler. - * Locking: called with is->slock spinlock held. - */ -void fimc_isp_video_irq_handler(struct fimc_is *is) -{ - struct fimc_is_video *video = &is->isp.video_capture; - struct vb2_v4l2_buffer *vbuf; - int buf_index; - - /* TODO: Ensure the DMA is really stopped in stop_streaming callback */ - if (!test_bit(ST_ISP_VID_CAP_STREAMING, &is->isp.state)) - return; - - buf_index = (is->i2h_cmd.args[1] - 1) % video->buf_count; - vbuf = &video->buffers[buf_index]->vb; - - vbuf->vb2_buf.timestamp = ktime_get_ns(); - vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); - - video->buf_mask &= ~BIT(buf_index); - fimc_is_hw_set_isp_buf_mask(is, video->buf_mask); -} - -static const struct vb2_ops isp_video_capture_qops = { - .queue_setup = isp_video_capture_queue_setup, - .buf_prepare = isp_video_capture_buffer_prepare, - .buf_queue = isp_video_capture_buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .start_streaming = isp_video_capture_start_streaming, - .stop_streaming = isp_video_capture_stop_streaming, -}; - -static int isp_video_open(struct file *file) -{ - struct fimc_isp *isp = video_drvdata(file); - struct exynos_video_entity *ve = &isp->video_capture.ve; - struct media_entity *me = &ve->vdev.entity; - int ret; - - if (mutex_lock_interruptible(&isp->video_lock)) - return -ERESTARTSYS; - - ret = v4l2_fh_open(file); - if (ret < 0) - goto unlock; - - ret = pm_runtime_resume_and_get(&isp->pdev->dev); - if (ret < 0) - goto rel_fh; - - if (v4l2_fh_is_singular_file(file)) { - mutex_lock(&me->graph_obj.mdev->graph_mutex); - - ret = fimc_pipeline_call(ve, open, me, true); - - /* Mark the video pipeline as in use. */ - if (ret == 0) - me->use_count++; - - mutex_unlock(&me->graph_obj.mdev->graph_mutex); - } - if (!ret) - goto unlock; -rel_fh: - v4l2_fh_release(file); -unlock: - mutex_unlock(&isp->video_lock); - return ret; -} - -static int isp_video_release(struct file *file) -{ - struct fimc_isp *isp = video_drvdata(file); - struct fimc_is_video *ivc = &isp->video_capture; - struct media_entity *entity = &ivc->ve.vdev.entity; - struct media_device *mdev = entity->graph_obj.mdev; - bool is_singular_file; - - mutex_lock(&isp->video_lock); - - is_singular_file = v4l2_fh_is_singular_file(file); - - if (is_singular_file && ivc->streaming) { - media_pipeline_stop(entity); - ivc->streaming = 0; - } - - _vb2_fop_release(file, NULL); - - if (is_singular_file) { - fimc_pipeline_call(&ivc->ve, close); - - mutex_lock(&mdev->graph_mutex); - entity->use_count--; - mutex_unlock(&mdev->graph_mutex); - } - - pm_runtime_put(&isp->pdev->dev); - mutex_unlock(&isp->video_lock); - - return 0; -} - -static const struct v4l2_file_operations isp_video_fops = { - .owner = THIS_MODULE, - .open = isp_video_open, - .release = isp_video_release, - .poll = vb2_fop_poll, - .unlocked_ioctl = video_ioctl2, - .mmap = vb2_fop_mmap, -}; - -/* - * Video node ioctl operations - */ -static int isp_video_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct fimc_isp *isp = video_drvdata(file); - - __fimc_vidioc_querycap(&isp->pdev->dev, cap); - return 0; -} - -static int isp_video_enum_fmt(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - const struct fimc_fmt *fmt; - - if (f->index >= FIMC_ISP_NUM_FORMATS) - return -EINVAL; - - fmt = fimc_isp_find_format(NULL, NULL, f->index); - if (WARN_ON(fmt == NULL)) - return -EINVAL; - - f->pixelformat = fmt->fourcc; - - return 0; -} - -static int isp_video_g_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct fimc_isp *isp = video_drvdata(file); - - f->fmt.pix_mp = isp->video_capture.pixfmt; - return 0; -} - -static void __isp_video_try_fmt(struct fimc_isp *isp, - struct v4l2_pix_format_mplane *pixm, - const struct fimc_fmt **fmt) -{ - const struct fimc_fmt *__fmt; - - __fmt = fimc_isp_find_format(&pixm->pixelformat, NULL, 2); - - if (fmt) - *fmt = __fmt; - - pixm->colorspace = V4L2_COLORSPACE_SRGB; - pixm->field = V4L2_FIELD_NONE; - pixm->num_planes = __fmt->memplanes; - pixm->pixelformat = __fmt->fourcc; - /* - * TODO: double check with the docmentation these width/height - * constraints are correct. - */ - v4l_bound_align_image(&pixm->width, FIMC_ISP_SOURCE_WIDTH_MIN, - FIMC_ISP_SOURCE_WIDTH_MAX, 3, - &pixm->height, FIMC_ISP_SOURCE_HEIGHT_MIN, - FIMC_ISP_SOURCE_HEIGHT_MAX, 0, 0); -} - -static int isp_video_try_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct fimc_isp *isp = video_drvdata(file); - - __isp_video_try_fmt(isp, &f->fmt.pix_mp, NULL); - return 0; -} - -static int isp_video_s_fmt_mplane(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct fimc_isp *isp = video_drvdata(file); - struct fimc_is *is = fimc_isp_to_is(isp); - struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; - const struct fimc_fmt *ifmt = NULL; - struct param_dma_output *dma = __get_isp_dma2(is); - - __isp_video_try_fmt(isp, pixm, &ifmt); - - if (WARN_ON(ifmt == NULL)) - return -EINVAL; - - dma->format = DMA_OUTPUT_FORMAT_BAYER; - dma->order = DMA_OUTPUT_ORDER_GB_BG; - dma->plane = ifmt->memplanes; - dma->bitwidth = ifmt->depth[0]; - dma->width = pixm->width; - dma->height = pixm->height; - - fimc_is_mem_barrier(); - - isp->video_capture.format = ifmt; - isp->video_capture.pixfmt = *pixm; - - return 0; -} - -/* - * Check for source/sink format differences at each link. - * Return 0 if the formats match or -EPIPE otherwise. - */ -static int isp_video_pipeline_validate(struct fimc_isp *isp) -{ - struct v4l2_subdev *sd = &isp->subdev; - struct v4l2_subdev_format sink_fmt, src_fmt; - struct media_pad *pad; - int ret; - - while (1) { - /* Retrieve format at the sink pad */ - pad = &sd->entity.pads[0]; - if (!(pad->flags & MEDIA_PAD_FL_SINK)) - break; - 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_pad(pad); - if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) - 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 isp_video_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct fimc_isp *isp = video_drvdata(file); - struct exynos_video_entity *ve = &isp->video_capture.ve; - struct media_entity *me = &ve->vdev.entity; - int ret; - - ret = media_pipeline_start(me, &ve->pipe->mp); - if (ret < 0) - return ret; - - ret = isp_video_pipeline_validate(isp); - if (ret < 0) - goto p_stop; - - ret = vb2_ioctl_streamon(file, priv, type); - if (ret < 0) - goto p_stop; - - isp->video_capture.streaming = 1; - return 0; -p_stop: - media_pipeline_stop(me); - return ret; -} - -static int isp_video_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct fimc_isp *isp = video_drvdata(file); - struct fimc_is_video *video = &isp->video_capture; - int ret; - - ret = vb2_ioctl_streamoff(file, priv, type); - if (ret < 0) - return ret; - - media_pipeline_stop(&video->ve.vdev.entity); - video->streaming = 0; - return 0; -} - -static int isp_video_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct fimc_isp *isp = video_drvdata(file); - int ret; - - ret = vb2_ioctl_reqbufs(file, priv, rb); - if (ret < 0) - return ret; - - if (rb->count && rb->count < FIMC_ISP_REQ_BUFS_MIN) { - rb->count = 0; - vb2_ioctl_reqbufs(file, priv, rb); - ret = -ENOMEM; - } - - isp->video_capture.reqbufs_count = rb->count; - return ret; -} - -static const struct v4l2_ioctl_ops isp_video_ioctl_ops = { - .vidioc_querycap = isp_video_querycap, - .vidioc_enum_fmt_vid_cap = isp_video_enum_fmt, - .vidioc_try_fmt_vid_cap_mplane = isp_video_try_fmt_mplane, - .vidioc_s_fmt_vid_cap_mplane = isp_video_s_fmt_mplane, - .vidioc_g_fmt_vid_cap_mplane = isp_video_g_fmt_mplane, - .vidioc_reqbufs = isp_video_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_streamon = isp_video_streamon, - .vidioc_streamoff = isp_video_streamoff, -}; - -int fimc_isp_video_device_register(struct fimc_isp *isp, - struct v4l2_device *v4l2_dev, - enum v4l2_buf_type type) -{ - struct vb2_queue *q = &isp->video_capture.vb_queue; - struct fimc_is_video *iv; - struct video_device *vdev; - int ret; - - if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - iv = &isp->video_capture; - else - return -ENOSYS; - - mutex_init(&isp->video_lock); - INIT_LIST_HEAD(&iv->pending_buf_q); - INIT_LIST_HEAD(&iv->active_buf_q); - iv->format = fimc_isp_find_format(NULL, NULL, 0); - iv->pixfmt.width = IS_DEFAULT_WIDTH; - iv->pixfmt.height = IS_DEFAULT_HEIGHT; - iv->pixfmt.pixelformat = iv->format->fourcc; - iv->pixfmt.colorspace = V4L2_COLORSPACE_SRGB; - iv->reqbufs_count = 0; - - memset(q, 0, sizeof(*q)); - q->type = type; - q->io_modes = VB2_MMAP | VB2_USERPTR; - q->ops = &isp_video_capture_qops; - q->mem_ops = &vb2_dma_contig_memops; - q->buf_struct_size = sizeof(struct isp_video_buf); - q->drv_priv = isp; - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &isp->video_lock; - q->dev = &isp->pdev->dev; - - ret = vb2_queue_init(q); - if (ret < 0) - return ret; - - vdev = &iv->ve.vdev; - memset(vdev, 0, sizeof(*vdev)); - strscpy(vdev->name, "fimc-is-isp.capture", sizeof(vdev->name)); - vdev->queue = q; - vdev->fops = &isp_video_fops; - vdev->ioctl_ops = &isp_video_ioctl_ops; - vdev->v4l2_dev = v4l2_dev; - vdev->minor = -1; - vdev->release = video_device_release_empty; - vdev->lock = &isp->video_lock; - vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE; - - iv->pad.flags = MEDIA_PAD_FL_SINK; - ret = media_entity_pads_init(&vdev->entity, 1, &iv->pad); - if (ret < 0) - return ret; - - video_set_drvdata(vdev, isp); - - ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); - if (ret < 0) { - media_entity_cleanup(&vdev->entity); - return ret; - } - - v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n", - vdev->name, video_device_node_name(vdev)); - - return 0; -} - -void fimc_isp_video_device_unregister(struct fimc_isp *isp, - enum v4l2_buf_type type) -{ - struct exynos_video_entity *ve; - - if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - ve = &isp->video_capture.ve; - else - return; - - mutex_lock(&isp->video_lock); - - if (video_is_registered(&ve->vdev)) { - video_unregister_device(&ve->vdev); - media_entity_cleanup(&ve->vdev.entity); - ve->pipe = NULL; - } - - mutex_unlock(&isp->video_lock); -} diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.h b/drivers/media/platform/exynos4-is/fimc-isp-video.h deleted file mode 100644 index edcb3a5e3cb9..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ -#ifndef FIMC_ISP_VIDEO__ -#define FIMC_ISP_VIDEO__ - -#include <media/videobuf2-v4l2.h> -#include "fimc-isp.h" - -#ifdef CONFIG_VIDEO_EXYNOS4_ISP_DMA_CAPTURE -int fimc_isp_video_device_register(struct fimc_isp *isp, - struct v4l2_device *v4l2_dev, - enum v4l2_buf_type type); - -void fimc_isp_video_device_unregister(struct fimc_isp *isp, - enum v4l2_buf_type type); - -void fimc_isp_video_irq_handler(struct fimc_is *is); -#else -static inline void fimc_isp_video_irq_handler(struct fimc_is *is) -{ -} - -static inline int fimc_isp_video_device_register(struct fimc_isp *isp, - struct v4l2_device *v4l2_dev, - enum v4l2_buf_type type) -{ - return 0; -} - -void fimc_isp_video_device_unregister(struct fimc_isp *isp, - enum v4l2_buf_type type) -{ -} -#endif /* !CONFIG_VIDEO_EXYNOS4_ISP_DMA_CAPTURE */ - -#endif /* FIMC_ISP_VIDEO__ */ diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c deleted file mode 100644 index b85986e50f46..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ /dev/null @@ -1,789 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * - * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com> - * Younghwan Joo <yhwan.joo@samsung.com> - */ -#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__ - -#include <linux/device.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/printk.h> -#include <linux/pm_runtime.h> -#include <linux/slab.h> -#include <linux/types.h> -#include <media/v4l2-device.h> - -#include "media-dev.h" -#include "fimc-isp-video.h" -#include "fimc-is-command.h" -#include "fimc-is-param.h" -#include "fimc-is-regs.h" -#include "fimc-is.h" - -int fimc_isp_debug; -module_param_named(debug_isp, fimc_isp_debug, int, S_IRUGO | S_IWUSR); - -static const struct fimc_fmt fimc_isp_formats[FIMC_ISP_NUM_FORMATS] = { - { - .fourcc = V4L2_PIX_FMT_SGRBG8, - .depth = { 8 }, - .color = FIMC_FMT_RAW8, - .memplanes = 1, - .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG10, - .depth = { 10 }, - .color = FIMC_FMT_RAW10, - .memplanes = 1, - .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG12, - .depth = { 12 }, - .color = FIMC_FMT_RAW12, - .memplanes = 1, - .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, - }, -}; - -/** - * fimc_isp_find_format - lookup color format by fourcc or media bus code - * @pixelformat: fourcc to match, ignored if null - * @mbus_code: media bus code to match, ignored if null - * @index: index to the fimc_isp_formats array, ignored if negative - */ -const struct fimc_fmt *fimc_isp_find_format(const u32 *pixelformat, - const u32 *mbus_code, int index) -{ - const struct fimc_fmt *fmt, *def_fmt = NULL; - unsigned int i; - int id = 0; - - if (index >= (int)ARRAY_SIZE(fimc_isp_formats)) - return NULL; - - for (i = 0; i < ARRAY_SIZE(fimc_isp_formats); ++i) { - fmt = &fimc_isp_formats[i]; - 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; -} - -void fimc_isp_irq_handler(struct fimc_is *is) -{ - is->i2h_cmd.args[0] = mcuctl_read(is, MCUCTL_REG_ISSR(20)); - is->i2h_cmd.args[1] = mcuctl_read(is, MCUCTL_REG_ISSR(21)); - - fimc_is_fw_clear_irq1(is, FIMC_IS_INT_FRAME_DONE_ISP); - fimc_isp_video_irq_handler(is); - - wake_up(&is->irq_queue); -} - -/* Capture subdev media entity operations */ -static int fimc_is_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - return 0; -} - -static const struct media_entity_operations fimc_is_subdev_media_ops = { - .link_setup = fimc_is_link_setup, -}; - -static int fimc_is_subdev_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - const struct fimc_fmt *fmt; - - fmt = fimc_isp_find_format(NULL, NULL, code->index); - if (!fmt) - return -EINVAL; - code->code = fmt->mbus_code; - return 0; -} - -static int fimc_isp_subdev_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct fimc_isp *isp = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *mf = &fmt->format; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - *mf = *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); - return 0; - } - - mf->colorspace = V4L2_COLORSPACE_SRGB; - - mutex_lock(&isp->subdev_lock); - - if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { - /* ISP OTF input image format */ - *mf = isp->sink_fmt; - } else { - /* ISP OTF output image format */ - *mf = isp->src_fmt; - - if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) { - mf->colorspace = V4L2_COLORSPACE_JPEG; - mf->code = MEDIA_BUS_FMT_YUV10_1X30; - } - } - - mutex_unlock(&isp->subdev_lock); - - isp_dbg(1, sd, "%s: pad%d: fmt: 0x%x, %dx%d\n", __func__, - fmt->pad, mf->code, mf->width, mf->height); - - return 0; -} - -static void __isp_subdev_try_format(struct fimc_isp *isp, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct v4l2_mbus_framefmt *mf = &fmt->format; - struct v4l2_mbus_framefmt *format; - - mf->colorspace = V4L2_COLORSPACE_SRGB; - - if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { - v4l_bound_align_image(&mf->width, FIMC_ISP_SINK_WIDTH_MIN, - FIMC_ISP_SINK_WIDTH_MAX, 0, - &mf->height, FIMC_ISP_SINK_HEIGHT_MIN, - FIMC_ISP_SINK_HEIGHT_MAX, 0, 0); - mf->code = MEDIA_BUS_FMT_SGRBG10_1X10; - } else { - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) - format = v4l2_subdev_get_try_format(&isp->subdev, - sd_state, - FIMC_ISP_SD_PAD_SINK); - else - format = &isp->sink_fmt; - - /* Allow changing format only on sink pad */ - mf->width = format->width - FIMC_ISP_CAC_MARGIN_WIDTH; - mf->height = format->height - FIMC_ISP_CAC_MARGIN_HEIGHT; - - if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) { - mf->code = MEDIA_BUS_FMT_YUV10_1X30; - mf->colorspace = V4L2_COLORSPACE_JPEG; - } else { - mf->code = format->code; - } - } -} - -static int fimc_isp_subdev_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct fimc_isp *isp = v4l2_get_subdevdata(sd); - struct fimc_is *is = fimc_isp_to_is(isp); - struct v4l2_mbus_framefmt *mf = &fmt->format; - int ret = 0; - - isp_dbg(1, sd, "%s: pad%d: code: 0x%x, %dx%d\n", - __func__, fmt->pad, mf->code, mf->width, mf->height); - - mutex_lock(&isp->subdev_lock); - __isp_subdev_try_format(isp, sd_state, fmt); - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); - *mf = fmt->format; - - /* Propagate format to the source pads */ - if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { - struct v4l2_subdev_format format = *fmt; - unsigned int pad; - - for (pad = FIMC_ISP_SD_PAD_SRC_FIFO; - pad < FIMC_ISP_SD_PADS_NUM; pad++) { - format.pad = pad; - __isp_subdev_try_format(isp, sd_state, - &format); - mf = v4l2_subdev_get_try_format(sd, sd_state, - pad); - *mf = format.format; - } - } - } else { - if (!media_entity_is_streaming(&sd->entity)) { - if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { - struct v4l2_subdev_format format = *fmt; - - isp->sink_fmt = *mf; - - format.pad = FIMC_ISP_SD_PAD_SRC_DMA; - __isp_subdev_try_format(isp, sd_state, - &format); - - isp->src_fmt = format.format; - __is_set_frame_size(is, &isp->src_fmt); - } else { - isp->src_fmt = *mf; - } - } else { - ret = -EBUSY; - } - } - - mutex_unlock(&isp->subdev_lock); - return ret; -} - -static int fimc_isp_subdev_s_stream(struct v4l2_subdev *sd, int on) -{ - struct fimc_isp *isp = v4l2_get_subdevdata(sd); - struct fimc_is *is = fimc_isp_to_is(isp); - int ret; - - isp_dbg(1, sd, "%s: on: %d\n", __func__, on); - - if (!test_bit(IS_ST_INIT_DONE, &is->state)) - return -EBUSY; - - fimc_is_mem_barrier(); - - if (on) { - if (__get_pending_param_count(is)) { - ret = fimc_is_itf_s_param(is, true); - if (ret < 0) - return ret; - } - - isp_dbg(1, sd, "changing mode to %d\n", is->config_index); - - ret = fimc_is_itf_mode_change(is); - if (ret) - return -EINVAL; - - clear_bit(IS_ST_STREAM_ON, &is->state); - fimc_is_hw_stream_on(is); - ret = fimc_is_wait_event(is, IS_ST_STREAM_ON, 1, - FIMC_IS_CONFIG_TIMEOUT); - if (ret < 0) { - v4l2_err(sd, "stream on timeout\n"); - return ret; - } - } else { - clear_bit(IS_ST_STREAM_OFF, &is->state); - fimc_is_hw_stream_off(is); - ret = fimc_is_wait_event(is, IS_ST_STREAM_OFF, 1, - FIMC_IS_CONFIG_TIMEOUT); - if (ret < 0) { - v4l2_err(sd, "stream off timeout\n"); - return ret; - } - is->setfile.sub_index = 0; - } - - return 0; -} - -static int fimc_isp_subdev_s_power(struct v4l2_subdev *sd, int on) -{ - struct fimc_isp *isp = v4l2_get_subdevdata(sd); - struct fimc_is *is = fimc_isp_to_is(isp); - int ret = 0; - - pr_debug("on: %d\n", on); - - if (on) { - ret = pm_runtime_resume_and_get(&is->pdev->dev); - if (ret < 0) - return ret; - - set_bit(IS_ST_PWR_ON, &is->state); - - ret = fimc_is_start_firmware(is); - if (ret < 0) { - v4l2_err(sd, "firmware booting failed\n"); - pm_runtime_put(&is->pdev->dev); - return ret; - } - set_bit(IS_ST_PWR_SUBIP_ON, &is->state); - - ret = fimc_is_hw_initialize(is); - } else { - /* Close sensor */ - if (!test_bit(IS_ST_PWR_ON, &is->state)) { - fimc_is_hw_close_sensor(is, 0); - - ret = fimc_is_wait_event(is, IS_ST_OPEN_SENSOR, 0, - FIMC_IS_CONFIG_TIMEOUT); - if (ret < 0) { - v4l2_err(sd, "sensor close timeout\n"); - return ret; - } - } - - /* SUB IP power off */ - if (test_bit(IS_ST_PWR_SUBIP_ON, &is->state)) { - fimc_is_hw_subip_power_off(is); - ret = fimc_is_wait_event(is, IS_ST_PWR_SUBIP_ON, 0, - FIMC_IS_CONFIG_TIMEOUT); - if (ret < 0) { - v4l2_err(sd, "sub-IP power off timeout\n"); - return ret; - } - } - - fimc_is_cpu_set_power(is, 0); - pm_runtime_put_sync(&is->pdev->dev); - - clear_bit(IS_ST_PWR_ON, &is->state); - clear_bit(IS_ST_INIT_DONE, &is->state); - is->state = 0; - is->config[is->config_index].p_region_index[0] = 0; - is->config[is->config_index].p_region_index[1] = 0; - set_bit(IS_ST_IDLE, &is->state); - wmb(); - } - - return ret; -} - -static int fimc_isp_subdev_open(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct v4l2_mbus_framefmt *format; - struct v4l2_mbus_framefmt fmt = { - .colorspace = V4L2_COLORSPACE_SRGB, - .code = fimc_isp_formats[0].mbus_code, - .width = DEFAULT_PREVIEW_STILL_WIDTH + FIMC_ISP_CAC_MARGIN_WIDTH, - .height = DEFAULT_PREVIEW_STILL_HEIGHT + FIMC_ISP_CAC_MARGIN_HEIGHT, - .field = V4L2_FIELD_NONE, - }; - - format = v4l2_subdev_get_try_format(sd, fh->state, - FIMC_ISP_SD_PAD_SINK); - *format = fmt; - - format = v4l2_subdev_get_try_format(sd, fh->state, - FIMC_ISP_SD_PAD_SRC_FIFO); - fmt.width = DEFAULT_PREVIEW_STILL_WIDTH; - fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT; - *format = fmt; - - format = v4l2_subdev_get_try_format(sd, fh->state, - FIMC_ISP_SD_PAD_SRC_DMA); - *format = fmt; - - return 0; -} - -static int fimc_isp_subdev_registered(struct v4l2_subdev *sd) -{ - struct fimc_isp *isp = v4l2_get_subdevdata(sd); - int ret; - - /* Use pipeline object allocated by the media device. */ - isp->video_capture.ve.pipe = v4l2_get_subdev_hostdata(sd); - - ret = fimc_isp_video_device_register(isp, sd->v4l2_dev, - V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - if (ret < 0) - isp->video_capture.ve.pipe = NULL; - - return ret; -} - -static void fimc_isp_subdev_unregistered(struct v4l2_subdev *sd) -{ - struct fimc_isp *isp = v4l2_get_subdevdata(sd); - - fimc_isp_video_device_unregister(isp, - V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); -} - -static const struct v4l2_subdev_internal_ops fimc_is_subdev_internal_ops = { - .registered = fimc_isp_subdev_registered, - .unregistered = fimc_isp_subdev_unregistered, - .open = fimc_isp_subdev_open, -}; - -static const struct v4l2_subdev_pad_ops fimc_is_subdev_pad_ops = { - .enum_mbus_code = fimc_is_subdev_enum_mbus_code, - .get_fmt = fimc_isp_subdev_get_fmt, - .set_fmt = fimc_isp_subdev_set_fmt, -}; - -static const struct v4l2_subdev_video_ops fimc_is_subdev_video_ops = { - .s_stream = fimc_isp_subdev_s_stream, -}; - -static const struct v4l2_subdev_core_ops fimc_is_core_ops = { - .s_power = fimc_isp_subdev_s_power, -}; - -static const struct v4l2_subdev_ops fimc_is_subdev_ops = { - .core = &fimc_is_core_ops, - .video = &fimc_is_subdev_video_ops, - .pad = &fimc_is_subdev_pad_ops, -}; - -static int __ctrl_set_white_balance(struct fimc_is *is, int value) -{ - switch (value) { - case V4L2_WHITE_BALANCE_AUTO: - __is_set_isp_awb(is, ISP_AWB_COMMAND_AUTO, 0); - break; - case V4L2_WHITE_BALANCE_DAYLIGHT: - __is_set_isp_awb(is, ISP_AWB_COMMAND_ILLUMINATION, - ISP_AWB_ILLUMINATION_DAYLIGHT); - break; - case V4L2_WHITE_BALANCE_CLOUDY: - __is_set_isp_awb(is, ISP_AWB_COMMAND_ILLUMINATION, - ISP_AWB_ILLUMINATION_CLOUDY); - break; - case V4L2_WHITE_BALANCE_INCANDESCENT: - __is_set_isp_awb(is, ISP_AWB_COMMAND_ILLUMINATION, - ISP_AWB_ILLUMINATION_TUNGSTEN); - break; - case V4L2_WHITE_BALANCE_FLUORESCENT: - __is_set_isp_awb(is, ISP_AWB_COMMAND_ILLUMINATION, - ISP_AWB_ILLUMINATION_FLUORESCENT); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int __ctrl_set_aewb_lock(struct fimc_is *is, - struct v4l2_ctrl *ctrl) -{ - bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE; - bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE; - struct isp_param *isp = &is->is_p_region->parameter.isp; - int cmd, ret; - - cmd = ae_lock ? ISP_AA_COMMAND_STOP : ISP_AA_COMMAND_START; - isp->aa.cmd = cmd; - isp->aa.target = ISP_AA_TARGET_AE; - fimc_is_set_param_bit(is, PARAM_ISP_AA); - is->af.ae_lock_state = ae_lock; - wmb(); - - ret = fimc_is_itf_s_param(is, false); - if (ret < 0) - return ret; - - cmd = awb_lock ? ISP_AA_COMMAND_STOP : ISP_AA_COMMAND_START; - isp->aa.cmd = cmd; - isp->aa.target = ISP_AA_TARGET_AE; - fimc_is_set_param_bit(is, PARAM_ISP_AA); - is->af.awb_lock_state = awb_lock; - wmb(); - - return fimc_is_itf_s_param(is, false); -} - -/* Supported manual ISO values */ -static const s64 iso_qmenu[] = { - 50, 100, 200, 400, 800, -}; - -static int __ctrl_set_iso(struct fimc_is *is, int value) -{ - unsigned int idx, iso; - - if (value == V4L2_ISO_SENSITIVITY_AUTO) { - __is_set_isp_iso(is, ISP_ISO_COMMAND_AUTO, 0); - return 0; - } - idx = is->isp.ctrls.iso->val; - if (idx >= ARRAY_SIZE(iso_qmenu)) - return -EINVAL; - - iso = iso_qmenu[idx]; - __is_set_isp_iso(is, ISP_ISO_COMMAND_MANUAL, iso); - return 0; -} - -static int __ctrl_set_metering(struct fimc_is *is, unsigned int value) -{ - unsigned int val; - - switch (value) { - case V4L2_EXPOSURE_METERING_AVERAGE: - val = ISP_METERING_COMMAND_AVERAGE; - break; - case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED: - val = ISP_METERING_COMMAND_CENTER; - break; - case V4L2_EXPOSURE_METERING_SPOT: - val = ISP_METERING_COMMAND_SPOT; - break; - case V4L2_EXPOSURE_METERING_MATRIX: - val = ISP_METERING_COMMAND_MATRIX; - break; - default: - return -EINVAL; - } - - __is_set_isp_metering(is, IS_METERING_CONFIG_CMD, val); - return 0; -} - -static int __ctrl_set_afc(struct fimc_is *is, int value) -{ - switch (value) { - case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED: - __is_set_isp_afc(is, ISP_AFC_COMMAND_DISABLE, 0); - break; - case V4L2_CID_POWER_LINE_FREQUENCY_50HZ: - __is_set_isp_afc(is, ISP_AFC_COMMAND_MANUAL, 50); - break; - case V4L2_CID_POWER_LINE_FREQUENCY_60HZ: - __is_set_isp_afc(is, ISP_AFC_COMMAND_MANUAL, 60); - break; - case V4L2_CID_POWER_LINE_FREQUENCY_AUTO: - __is_set_isp_afc(is, ISP_AFC_COMMAND_AUTO, 0); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int __ctrl_set_image_effect(struct fimc_is *is, int value) -{ - static const u8 effects[][2] = { - { V4L2_COLORFX_NONE, ISP_IMAGE_EFFECT_DISABLE }, - { V4L2_COLORFX_BW, ISP_IMAGE_EFFECT_MONOCHROME }, - { V4L2_COLORFX_SEPIA, ISP_IMAGE_EFFECT_SEPIA }, - { V4L2_COLORFX_NEGATIVE, ISP_IMAGE_EFFECT_NEGATIVE_MONO }, - { 16 /* TODO */, ISP_IMAGE_EFFECT_NEGATIVE_COLOR }, - }; - int i; - - for (i = 0; i < ARRAY_SIZE(effects); i++) { - if (effects[i][0] != value) - continue; - - __is_set_isp_effect(is, effects[i][1]); - return 0; - } - - return -EINVAL; -} - -static int fimc_is_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct fimc_isp *isp = ctrl_to_fimc_isp(ctrl); - struct fimc_is *is = fimc_isp_to_is(isp); - bool set_param = true; - int ret = 0; - - switch (ctrl->id) { - case V4L2_CID_CONTRAST: - __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_CONTRAST, - ctrl->val); - break; - - case V4L2_CID_SATURATION: - __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_SATURATION, - ctrl->val); - break; - - case V4L2_CID_SHARPNESS: - __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_SHARPNESS, - ctrl->val); - break; - - case V4L2_CID_EXPOSURE_ABSOLUTE: - __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_EXPOSURE, - ctrl->val); - break; - - case V4L2_CID_BRIGHTNESS: - __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS, - ctrl->val); - break; - - case V4L2_CID_HUE: - __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_HUE, - ctrl->val); - break; - - case V4L2_CID_EXPOSURE_METERING: - ret = __ctrl_set_metering(is, ctrl->val); - break; - - case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: - ret = __ctrl_set_white_balance(is, ctrl->val); - break; - - case V4L2_CID_3A_LOCK: - ret = __ctrl_set_aewb_lock(is, ctrl); - set_param = false; - break; - - case V4L2_CID_ISO_SENSITIVITY_AUTO: - ret = __ctrl_set_iso(is, ctrl->val); - break; - - case V4L2_CID_POWER_LINE_FREQUENCY: - ret = __ctrl_set_afc(is, ctrl->val); - break; - - case V4L2_CID_COLORFX: - __ctrl_set_image_effect(is, ctrl->val); - break; - - default: - ret = -EINVAL; - break; - } - - if (ret < 0) { - v4l2_err(&isp->subdev, "Failed to set control: %s (%d)\n", - ctrl->name, ctrl->val); - return ret; - } - - if (set_param && test_bit(IS_ST_STREAM_ON, &is->state)) - return fimc_is_itf_s_param(is, true); - - return 0; -} - -static const struct v4l2_ctrl_ops fimc_isp_ctrl_ops = { - .s_ctrl = fimc_is_s_ctrl, -}; - -static void __isp_subdev_set_default_format(struct fimc_isp *isp) -{ - struct fimc_is *is = fimc_isp_to_is(isp); - - isp->sink_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH + - FIMC_ISP_CAC_MARGIN_WIDTH; - isp->sink_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT + - FIMC_ISP_CAC_MARGIN_HEIGHT; - isp->sink_fmt.code = MEDIA_BUS_FMT_SGRBG10_1X10; - - isp->src_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH; - isp->src_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT; - isp->src_fmt.code = MEDIA_BUS_FMT_SGRBG10_1X10; - __is_set_frame_size(is, &isp->src_fmt); -} - -int fimc_isp_subdev_create(struct fimc_isp *isp) -{ - const struct v4l2_ctrl_ops *ops = &fimc_isp_ctrl_ops; - struct v4l2_ctrl_handler *handler = &isp->ctrls.handler; - struct v4l2_subdev *sd = &isp->subdev; - struct fimc_isp_ctrls *ctrls = &isp->ctrls; - int ret; - - mutex_init(&isp->subdev_lock); - - v4l2_subdev_init(sd, &fimc_is_subdev_ops); - - sd->owner = THIS_MODULE; - sd->grp_id = GRP_ID_FIMC_IS; - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - snprintf(sd->name, sizeof(sd->name), "FIMC-IS-ISP"); - - sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; - isp->subdev_pads[FIMC_ISP_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_FIFO].flags = MEDIA_PAD_FL_SOURCE; - isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_DMA].flags = MEDIA_PAD_FL_SOURCE; - ret = media_entity_pads_init(&sd->entity, FIMC_ISP_SD_PADS_NUM, - isp->subdev_pads); - if (ret) - return ret; - - v4l2_ctrl_handler_init(handler, 20); - - ctrls->saturation = v4l2_ctrl_new_std(handler, ops, V4L2_CID_SATURATION, - -2, 2, 1, 0); - ctrls->brightness = v4l2_ctrl_new_std(handler, ops, V4L2_CID_BRIGHTNESS, - -4, 4, 1, 0); - ctrls->contrast = v4l2_ctrl_new_std(handler, ops, V4L2_CID_CONTRAST, - -2, 2, 1, 0); - ctrls->sharpness = v4l2_ctrl_new_std(handler, ops, V4L2_CID_SHARPNESS, - -2, 2, 1, 0); - ctrls->hue = v4l2_ctrl_new_std(handler, ops, V4L2_CID_HUE, - -2, 2, 1, 0); - - ctrls->auto_wb = v4l2_ctrl_new_std_menu(handler, ops, - V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, - 8, ~0x14e, V4L2_WHITE_BALANCE_AUTO); - - ctrls->exposure = v4l2_ctrl_new_std(handler, ops, - V4L2_CID_EXPOSURE_ABSOLUTE, - -4, 4, 1, 0); - - ctrls->exp_metering = v4l2_ctrl_new_std_menu(handler, ops, - V4L2_CID_EXPOSURE_METERING, 3, - ~0xf, V4L2_EXPOSURE_METERING_AVERAGE); - - v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0, - V4L2_CID_POWER_LINE_FREQUENCY_AUTO); - /* ISO sensitivity */ - ctrls->auto_iso = v4l2_ctrl_new_std_menu(handler, ops, - V4L2_CID_ISO_SENSITIVITY_AUTO, 1, 0, - V4L2_ISO_SENSITIVITY_AUTO); - - ctrls->iso = v4l2_ctrl_new_int_menu(handler, ops, - V4L2_CID_ISO_SENSITIVITY, ARRAY_SIZE(iso_qmenu) - 1, - ARRAY_SIZE(iso_qmenu)/2 - 1, iso_qmenu); - - ctrls->aewb_lock = v4l2_ctrl_new_std(handler, ops, - V4L2_CID_3A_LOCK, 0, 0x3, 0, 0); - - /* TODO: Add support for NEGATIVE_COLOR option */ - ctrls->colorfx = v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_COLORFX, - V4L2_COLORFX_SET_CBCR + 1, ~0x1000f, V4L2_COLORFX_NONE); - - if (handler->error) { - media_entity_cleanup(&sd->entity); - return handler->error; - } - - v4l2_ctrl_auto_cluster(2, &ctrls->auto_iso, - V4L2_ISO_SENSITIVITY_MANUAL, false); - - sd->ctrl_handler = handler; - sd->internal_ops = &fimc_is_subdev_internal_ops; - sd->entity.ops = &fimc_is_subdev_media_ops; - v4l2_set_subdevdata(sd, isp); - - __isp_subdev_set_default_format(isp); - - return 0; -} - -void fimc_isp_subdev_destroy(struct fimc_isp *isp) -{ - struct v4l2_subdev *sd = &isp->subdev; - - v4l2_device_unregister_subdev(sd); - media_entity_cleanup(&sd->entity); - v4l2_ctrl_handler_free(&isp->ctrls.handler); - v4l2_set_subdevdata(sd, NULL); -} diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h deleted file mode 100644 index 12017cd924d9..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-isp.h +++ /dev/null @@ -1,197 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * - * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com> - * Younghwan Joo <yhwan.joo@samsung.com> - */ -#ifndef FIMC_ISP_H_ -#define FIMC_ISP_H_ - -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/types.h> -#include <linux/videodev2.h> - -#include <media/media-entity.h> -#include <media/videobuf2-v4l2.h> -#include <media/v4l2-device.h> -#include <media/v4l2-mediabus.h> -#include <media/drv-intf/exynos-fimc.h> - -extern int fimc_isp_debug; - -#define isp_dbg(level, dev, fmt, arg...) \ - v4l2_dbg(level, fimc_isp_debug, dev, fmt, ## arg) - -/* FIXME: revisit these constraints */ -#define FIMC_ISP_SINK_WIDTH_MIN (16 + 8) -#define FIMC_ISP_SINK_HEIGHT_MIN (12 + 8) -#define FIMC_ISP_SOURCE_WIDTH_MIN 8 -#define FIMC_ISP_SOURCE_HEIGHT_MIN 8 -#define FIMC_ISP_CAC_MARGIN_WIDTH 16 -#define FIMC_ISP_CAC_MARGIN_HEIGHT 12 - -#define FIMC_ISP_SINK_WIDTH_MAX (4000 - 16) -#define FIMC_ISP_SINK_HEIGHT_MAX (4000 + 12) -#define FIMC_ISP_SOURCE_WIDTH_MAX 4000 -#define FIMC_ISP_SOURCE_HEIGHT_MAX 4000 - -#define FIMC_ISP_NUM_FORMATS 3 -#define FIMC_ISP_REQ_BUFS_MIN 2 -#define FIMC_ISP_REQ_BUFS_MAX 32 - -#define FIMC_ISP_SD_PAD_SINK 0 -#define FIMC_ISP_SD_PAD_SRC_FIFO 1 -#define FIMC_ISP_SD_PAD_SRC_DMA 2 -#define FIMC_ISP_SD_PADS_NUM 3 -#define FIMC_ISP_MAX_PLANES 1 - -/** - * struct fimc_isp_frame - source/target frame properties - * @width: full image width - * @height: full image height - * @rect: crop/composition rectangle - */ -struct fimc_isp_frame { - u16 width; - u16 height; - struct v4l2_rect rect; -}; - -struct fimc_isp_ctrls { - struct v4l2_ctrl_handler handler; - - /* Auto white balance */ - struct v4l2_ctrl *auto_wb; - /* Auto ISO control cluster */ - struct { - struct v4l2_ctrl *auto_iso; - struct v4l2_ctrl *iso; - }; - /* Adjust - contrast */ - struct v4l2_ctrl *contrast; - /* Adjust - saturation */ - struct v4l2_ctrl *saturation; - /* Adjust - sharpness */ - struct v4l2_ctrl *sharpness; - /* Adjust - brightness */ - struct v4l2_ctrl *brightness; - /* Adjust - hue */ - struct v4l2_ctrl *hue; - - /* Auto/manual exposure */ - struct v4l2_ctrl *auto_exp; - /* Manual exposure value */ - struct v4l2_ctrl *exposure; - /* AE/AWB lock/unlock */ - struct v4l2_ctrl *aewb_lock; - /* Exposure metering mode */ - struct v4l2_ctrl *exp_metering; - /* AFC */ - struct v4l2_ctrl *afc; - /* ISP image effect */ - struct v4l2_ctrl *colorfx; -}; - -struct isp_video_buf { - struct vb2_v4l2_buffer vb; - dma_addr_t dma_addr[FIMC_ISP_MAX_PLANES]; - unsigned int index; -}; - -#define to_isp_video_buf(_b) container_of(_b, struct isp_video_buf, vb) - -#define FIMC_ISP_MAX_BUFS 4 - -/** - * struct fimc_is_video - fimc-is video device structure - * @ve: video_device structure and media pipeline - * @type: video device type (CAPTURE/OUTPUT) - * @pad: video device media (sink) pad - * @pending_buf_q: pending buffers queue head - * @active_buf_q: a queue head of buffers scheduled in hardware - * @vb_queue: vb2 buffer queue - * @reqbufs_count: the number of buffers requested in REQBUFS ioctl - * @buf_count: number of video buffers scheduled in hardware - * @buf_mask: bitmask of the queued video buffer indices - * @frame_count: counter of frames dequeued to user space - * @streaming: is streaming in progress? - * @buffers: buffer info - * @format: current fimc pixel format - * @pixfmt: current pixel format - */ -struct fimc_is_video { - struct exynos_video_entity ve; - enum v4l2_buf_type type; - struct media_pad pad; - struct list_head pending_buf_q; - struct list_head active_buf_q; - struct vb2_queue vb_queue; - unsigned int reqbufs_count; - unsigned int buf_count; - unsigned int buf_mask; - unsigned int frame_count; - int streaming; - struct isp_video_buf *buffers[FIMC_ISP_MAX_BUFS]; - const struct fimc_fmt *format; - struct v4l2_pix_format_mplane pixfmt; -}; - -/* struct fimc_isp:state bit definitions */ -#define ST_ISP_VID_CAP_BUF_PREP 0 -#define ST_ISP_VID_CAP_STREAMING 1 - -/** - * struct fimc_isp - FIMC-IS ISP data structure - * @pdev: pointer to FIMC-IS platform device - * @subdev: ISP v4l2_subdev - * @subdev_pads: the ISP subdev media pads - * @src_fmt: source mediabus format - * @sink_fmt: sink mediabus format - * @test_pattern: test pattern controls - * @ctrls: v4l2 controls structure - * @video_lock: mutex serializing video device operations - * @subdev_lock: mutex serializing subdev operations - * @cac_margin_x: horizontal CAC margin in pixels - * @cac_margin_y: vertical CAC margin in pixels - * @state: driver state flags - * @video_capture: the ISP block video capture device - */ -struct fimc_isp { - struct platform_device *pdev; - struct v4l2_subdev subdev; - struct media_pad subdev_pads[FIMC_ISP_SD_PADS_NUM]; - struct v4l2_mbus_framefmt src_fmt; - struct v4l2_mbus_framefmt sink_fmt; - struct v4l2_ctrl *test_pattern; - struct fimc_isp_ctrls ctrls; - - struct mutex video_lock; - struct mutex subdev_lock; - - unsigned int cac_margin_x; - unsigned int cac_margin_y; - - unsigned long state; - - struct fimc_is_video video_capture; -}; - -#define ctrl_to_fimc_isp(_ctrl) \ - container_of(ctrl->handler, struct fimc_isp, ctrls.handler) - -struct fimc_is; - -int fimc_isp_subdev_create(struct fimc_isp *isp); -void fimc_isp_subdev_destroy(struct fimc_isp *isp); -void fimc_isp_irq_handler(struct fimc_is *is); -int fimc_is_create_controls(struct fimc_isp *isp); -int fimc_is_delete_controls(struct fimc_isp *isp); -const struct fimc_fmt *fimc_isp_find_format(const u32 *pixelformat, - const u32 *mbus_code, int index); -#endif /* FIMC_ISP_H_ */ diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.c b/drivers/media/platform/exynos4-is/fimc-lite-reg.c deleted file mode 100644 index 57996b4104b4..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-lite-reg.c +++ /dev/null @@ -1,346 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Register interface file for EXYNOS FIMC-LITE (camera interface) driver - * - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> -*/ - -#include <linux/bitops.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <media/drv-intf/exynos-fimc.h> - -#include "fimc-lite-reg.h" -#include "fimc-lite.h" -#include "fimc-core.h" - -#define FLITE_RESET_TIMEOUT 50 /* in ms */ - -void flite_hw_reset(struct fimc_lite *dev) -{ - unsigned long end = jiffies + msecs_to_jiffies(FLITE_RESET_TIMEOUT); - u32 cfg; - - cfg = readl(dev->regs + FLITE_REG_CIGCTRL); - cfg |= FLITE_REG_CIGCTRL_SWRST_REQ; - writel(cfg, dev->regs + FLITE_REG_CIGCTRL); - - while (time_is_after_jiffies(end)) { - cfg = readl(dev->regs + FLITE_REG_CIGCTRL); - if (cfg & FLITE_REG_CIGCTRL_SWRST_RDY) - break; - usleep_range(1000, 5000); - } - - cfg |= FLITE_REG_CIGCTRL_SWRST; - writel(cfg, dev->regs + FLITE_REG_CIGCTRL); -} - -void flite_hw_clear_pending_irq(struct fimc_lite *dev) -{ - u32 cfg = readl(dev->regs + FLITE_REG_CISTATUS); - cfg &= ~FLITE_REG_CISTATUS_IRQ_CAM; - writel(cfg, dev->regs + FLITE_REG_CISTATUS); -} - -u32 flite_hw_get_interrupt_source(struct fimc_lite *dev) -{ - u32 intsrc = readl(dev->regs + FLITE_REG_CISTATUS); - return intsrc & FLITE_REG_CISTATUS_IRQ_MASK; -} - -void flite_hw_clear_last_capture_end(struct fimc_lite *dev) -{ - - u32 cfg = readl(dev->regs + FLITE_REG_CISTATUS2); - cfg &= ~FLITE_REG_CISTATUS2_LASTCAPEND; - writel(cfg, dev->regs + FLITE_REG_CISTATUS2); -} - -void flite_hw_set_interrupt_mask(struct fimc_lite *dev) -{ - u32 cfg, intsrc; - - /* Select interrupts to be enabled for each output mode */ - if (atomic_read(&dev->out_path) == FIMC_IO_DMA) { - intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN | - FLITE_REG_CIGCTRL_IRQ_LASTEN | - FLITE_REG_CIGCTRL_IRQ_STARTEN | - FLITE_REG_CIGCTRL_IRQ_ENDEN; - } else { - /* An output to the FIMC-IS */ - intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN | - FLITE_REG_CIGCTRL_IRQ_LASTEN; - } - - cfg = readl(dev->regs + FLITE_REG_CIGCTRL); - cfg |= FLITE_REG_CIGCTRL_IRQ_DISABLE_MASK; - cfg &= ~intsrc; - writel(cfg, dev->regs + FLITE_REG_CIGCTRL); -} - -void flite_hw_capture_start(struct fimc_lite *dev) -{ - u32 cfg = readl(dev->regs + FLITE_REG_CIIMGCPT); - cfg |= FLITE_REG_CIIMGCPT_IMGCPTEN; - writel(cfg, dev->regs + FLITE_REG_CIIMGCPT); -} - -void flite_hw_capture_stop(struct fimc_lite *dev) -{ - u32 cfg = readl(dev->regs + FLITE_REG_CIIMGCPT); - cfg &= ~FLITE_REG_CIIMGCPT_IMGCPTEN; - writel(cfg, dev->regs + FLITE_REG_CIIMGCPT); -} - -/* - * Test pattern (color bars) enable/disable. External sensor - * pixel clock must be active for the test pattern to work. - */ -void flite_hw_set_test_pattern(struct fimc_lite *dev, bool on) -{ - u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL); - if (on) - cfg |= FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR; - else - cfg &= ~FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR; - writel(cfg, dev->regs + FLITE_REG_CIGCTRL); -} - -static const u32 src_pixfmt_map[8][3] = { - { MEDIA_BUS_FMT_YUYV8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR, - FLITE_REG_CIGCTRL_YUV422_1P }, - { MEDIA_BUS_FMT_YVYU8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB, - FLITE_REG_CIGCTRL_YUV422_1P }, - { MEDIA_BUS_FMT_UYVY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY, - FLITE_REG_CIGCTRL_YUV422_1P }, - { MEDIA_BUS_FMT_VYUY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY, - FLITE_REG_CIGCTRL_YUV422_1P }, - { MEDIA_BUS_FMT_SGRBG8_1X8, 0, FLITE_REG_CIGCTRL_RAW8 }, - { MEDIA_BUS_FMT_SGRBG10_1X10, 0, FLITE_REG_CIGCTRL_RAW10 }, - { MEDIA_BUS_FMT_SGRBG12_1X12, 0, FLITE_REG_CIGCTRL_RAW12 }, - { MEDIA_BUS_FMT_JPEG_1X8, 0, FLITE_REG_CIGCTRL_USER(1) }, -}; - -/* Set camera input pixel format and resolution */ -void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f) -{ - u32 pixelcode = f->fmt->mbus_code; - int i = ARRAY_SIZE(src_pixfmt_map); - u32 cfg; - - while (--i) { - if (src_pixfmt_map[i][0] == pixelcode) - break; - } - - if (i == 0 && src_pixfmt_map[i][0] != pixelcode) { - v4l2_err(&dev->ve.vdev, - "Unsupported pixel code, falling back to %#08x\n", - src_pixfmt_map[i][0]); - } - - cfg = readl(dev->regs + FLITE_REG_CIGCTRL); - cfg &= ~FLITE_REG_CIGCTRL_FMT_MASK; - cfg |= src_pixfmt_map[i][2]; - writel(cfg, dev->regs + FLITE_REG_CIGCTRL); - - cfg = readl(dev->regs + FLITE_REG_CISRCSIZE); - cfg &= ~(FLITE_REG_CISRCSIZE_ORDER422_MASK | - FLITE_REG_CISRCSIZE_SIZE_CAM_MASK); - cfg |= (f->f_width << 16) | f->f_height; - cfg |= src_pixfmt_map[i][1]; - writel(cfg, dev->regs + FLITE_REG_CISRCSIZE); -} - -/* Set the camera host input window offsets (cropping) */ -void flite_hw_set_window_offset(struct fimc_lite *dev, struct flite_frame *f) -{ - u32 hoff2, voff2; - u32 cfg; - - cfg = readl(dev->regs + FLITE_REG_CIWDOFST); - cfg &= ~FLITE_REG_CIWDOFST_OFST_MASK; - cfg |= (f->rect.left << 16) | f->rect.top; - cfg |= FLITE_REG_CIWDOFST_WINOFSEN; - writel(cfg, dev->regs + FLITE_REG_CIWDOFST); - - hoff2 = f->f_width - f->rect.width - f->rect.left; - voff2 = f->f_height - f->rect.height - f->rect.top; - - cfg = (hoff2 << 16) | voff2; - writel(cfg, dev->regs + FLITE_REG_CIWDOFST2); -} - -/* Select camera port (A, B) */ -static void flite_hw_set_camera_port(struct fimc_lite *dev, int id) -{ - u32 cfg = readl(dev->regs + FLITE_REG_CIGENERAL); - if (id == 0) - cfg &= ~FLITE_REG_CIGENERAL_CAM_B; - else - cfg |= FLITE_REG_CIGENERAL_CAM_B; - writel(cfg, dev->regs + FLITE_REG_CIGENERAL); -} - -/* Select serial or parallel bus, camera port (A,B) and set signals polarity */ -void flite_hw_set_camera_bus(struct fimc_lite *dev, - struct fimc_source_info *si) -{ - u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL); - unsigned int flags = si->flags; - - if (si->sensor_bus_type != FIMC_BUS_TYPE_MIPI_CSI2) { - cfg &= ~(FLITE_REG_CIGCTRL_SELCAM_MIPI | - FLITE_REG_CIGCTRL_INVPOLPCLK | - FLITE_REG_CIGCTRL_INVPOLVSYNC | - FLITE_REG_CIGCTRL_INVPOLHREF); - - if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) - cfg |= FLITE_REG_CIGCTRL_INVPOLPCLK; - - if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) - cfg |= FLITE_REG_CIGCTRL_INVPOLVSYNC; - - if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) - cfg |= FLITE_REG_CIGCTRL_INVPOLHREF; - } else { - cfg |= FLITE_REG_CIGCTRL_SELCAM_MIPI; - } - - writel(cfg, dev->regs + FLITE_REG_CIGCTRL); - - flite_hw_set_camera_port(dev, si->mux_id); -} - -static void flite_hw_set_pack12(struct fimc_lite *dev, int on) -{ - u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT); - - cfg &= ~FLITE_REG_CIODMAFMT_PACK12; - - if (on) - cfg |= FLITE_REG_CIODMAFMT_PACK12; - - writel(cfg, dev->regs + FLITE_REG_CIODMAFMT); -} - -static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f) -{ - static const u32 pixcode[4][2] = { - { MEDIA_BUS_FMT_YUYV8_2X8, FLITE_REG_CIODMAFMT_YCBYCR }, - { MEDIA_BUS_FMT_YVYU8_2X8, FLITE_REG_CIODMAFMT_YCRYCB }, - { MEDIA_BUS_FMT_UYVY8_2X8, FLITE_REG_CIODMAFMT_CBYCRY }, - { MEDIA_BUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY }, - }; - u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT); - int i = ARRAY_SIZE(pixcode); - - while (--i) - if (pixcode[i][0] == f->fmt->mbus_code) - break; - cfg &= ~FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK; - writel(cfg | pixcode[i][1], dev->regs + FLITE_REG_CIODMAFMT); -} - -void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f) -{ - u32 cfg; - - /* Maximum output pixel size */ - cfg = readl(dev->regs + FLITE_REG_CIOCAN); - cfg &= ~FLITE_REG_CIOCAN_MASK; - cfg |= (f->f_height << 16) | f->f_width; - writel(cfg, dev->regs + FLITE_REG_CIOCAN); - - /* DMA offsets */ - cfg = readl(dev->regs + FLITE_REG_CIOOFF); - cfg &= ~FLITE_REG_CIOOFF_MASK; - cfg |= (f->rect.top << 16) | f->rect.left; - writel(cfg, dev->regs + FLITE_REG_CIOOFF); -} - -void flite_hw_set_dma_buffer(struct fimc_lite *dev, struct flite_buffer *buf) -{ - unsigned int index; - u32 cfg; - - if (dev->dd->max_dma_bufs == 1) - index = 0; - else - index = buf->index; - - if (index == 0) - writel(buf->addr, dev->regs + FLITE_REG_CIOSA); - else - writel(buf->addr, dev->regs + FLITE_REG_CIOSAN(index - 1)); - - cfg = readl(dev->regs + FLITE_REG_CIFCNTSEQ); - cfg |= BIT(index); - writel(cfg, dev->regs + FLITE_REG_CIFCNTSEQ); -} - -void flite_hw_mask_dma_buffer(struct fimc_lite *dev, u32 index) -{ - u32 cfg; - - if (dev->dd->max_dma_bufs == 1) - index = 0; - - cfg = readl(dev->regs + FLITE_REG_CIFCNTSEQ); - cfg &= ~BIT(index); - writel(cfg, dev->regs + FLITE_REG_CIFCNTSEQ); -} - -/* Enable/disable output DMA, set output pixel size and offsets (composition) */ -void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f, - bool enable) -{ - u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL); - - if (!enable) { - cfg |= FLITE_REG_CIGCTRL_ODMA_DISABLE; - writel(cfg, dev->regs + FLITE_REG_CIGCTRL); - return; - } - - cfg &= ~FLITE_REG_CIGCTRL_ODMA_DISABLE; - writel(cfg, dev->regs + FLITE_REG_CIGCTRL); - - flite_hw_set_out_order(dev, f); - flite_hw_set_dma_window(dev, f); - flite_hw_set_pack12(dev, 0); -} - -void flite_hw_dump_regs(struct fimc_lite *dev, const char *label) -{ - struct { - u32 offset; - const char * const name; - } registers[] = { - { 0x00, "CISRCSIZE" }, - { 0x04, "CIGCTRL" }, - { 0x08, "CIIMGCPT" }, - { 0x0c, "CICPTSEQ" }, - { 0x10, "CIWDOFST" }, - { 0x14, "CIWDOFST2" }, - { 0x18, "CIODMAFMT" }, - { 0x20, "CIOCAN" }, - { 0x24, "CIOOFF" }, - { 0x30, "CIOSA" }, - { 0x40, "CISTATUS" }, - { 0x44, "CISTATUS2" }, - { 0xf0, "CITHOLD" }, - { 0xfc, "CIGENERAL" }, - }; - u32 i; - - v4l2_info(&dev->subdev, "--- %s ---\n", label); - - for (i = 0; i < ARRAY_SIZE(registers); i++) { - u32 cfg = readl(dev->regs + registers[i].offset); - v4l2_info(&dev->subdev, "%9s: 0x%08x\n", - registers[i].name, cfg); - } -} diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.h b/drivers/media/platform/exynos4-is/fimc-lite-reg.h deleted file mode 100644 index c5656e902750..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-lite-reg.h +++ /dev/null @@ -1,155 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - */ - -#ifndef FIMC_LITE_REG_H_ -#define FIMC_LITE_REG_H_ - -#include <linux/bitops.h> - -#include "fimc-lite.h" - -/* Camera Source size */ -#define FLITE_REG_CISRCSIZE 0x00 -#define FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR (0 << 14) -#define FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB (1 << 14) -#define FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY (2 << 14) -#define FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY (3 << 14) -#define FLITE_REG_CISRCSIZE_ORDER422_MASK (0x3 << 14) -#define FLITE_REG_CISRCSIZE_SIZE_CAM_MASK (0x3fff << 16 | 0x3fff) - -/* Global control */ -#define FLITE_REG_CIGCTRL 0x04 -#define FLITE_REG_CIGCTRL_YUV422_1P (0x1e << 24) -#define FLITE_REG_CIGCTRL_RAW8 (0x2a << 24) -#define FLITE_REG_CIGCTRL_RAW10 (0x2b << 24) -#define FLITE_REG_CIGCTRL_RAW12 (0x2c << 24) -#define FLITE_REG_CIGCTRL_RAW14 (0x2d << 24) -/* User defined formats. x = 0...15 */ -#define FLITE_REG_CIGCTRL_USER(x) ((0x30 + x - 1) << 24) -#define FLITE_REG_CIGCTRL_FMT_MASK (0x3f << 24) -#define FLITE_REG_CIGCTRL_SHADOWMASK_DISABLE BIT(21) -#define FLITE_REG_CIGCTRL_ODMA_DISABLE BIT(20) -#define FLITE_REG_CIGCTRL_SWRST_REQ BIT(19) -#define FLITE_REG_CIGCTRL_SWRST_RDY BIT(18) -#define FLITE_REG_CIGCTRL_SWRST BIT(17) -#define FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR BIT(15) -#define FLITE_REG_CIGCTRL_INVPOLPCLK BIT(14) -#define FLITE_REG_CIGCTRL_INVPOLVSYNC BIT(13) -#define FLITE_REG_CIGCTRL_INVPOLHREF BIT(12) -/* Interrupts mask bits (1 disables an interrupt) */ -#define FLITE_REG_CIGCTRL_IRQ_LASTEN BIT(8) -#define FLITE_REG_CIGCTRL_IRQ_ENDEN BIT(7) -#define FLITE_REG_CIGCTRL_IRQ_STARTEN BIT(6) -#define FLITE_REG_CIGCTRL_IRQ_OVFEN BIT(5) -#define FLITE_REG_CIGCTRL_IRQ_DISABLE_MASK (0xf << 5) -#define FLITE_REG_CIGCTRL_SELCAM_MIPI BIT(3) - -/* Image Capture Enable */ -#define FLITE_REG_CIIMGCPT 0x08 -#define FLITE_REG_CIIMGCPT_IMGCPTEN BIT(31) -#define FLITE_REG_CIIMGCPT_CPT_FREN BIT(25) -#define FLITE_REG_CIIMGCPT_CPT_MOD_FRCNT (1 << 18) -#define FLITE_REG_CIIMGCPT_CPT_MOD_FREN (0 << 18) - -/* Capture Sequence */ -#define FLITE_REG_CICPTSEQ 0x0c - -/* Camera Window Offset */ -#define FLITE_REG_CIWDOFST 0x10 -#define FLITE_REG_CIWDOFST_WINOFSEN BIT(31) -#define FLITE_REG_CIWDOFST_CLROVIY BIT(31) -#define FLITE_REG_CIWDOFST_CLROVFICB BIT(15) -#define FLITE_REG_CIWDOFST_CLROVFICR BIT(14) -#define FLITE_REG_CIWDOFST_OFST_MASK ((0x1fff << 16) | 0x1fff) - -/* Camera Window Offset2 */ -#define FLITE_REG_CIWDOFST2 0x14 - -/* Camera Output DMA Format */ -#define FLITE_REG_CIODMAFMT 0x18 -#define FLITE_REG_CIODMAFMT_RAW_CON BIT(15) -#define FLITE_REG_CIODMAFMT_PACK12 BIT(14) -#define FLITE_REG_CIODMAFMT_YCBYCR (0 << 4) -#define FLITE_REG_CIODMAFMT_YCRYCB (1 << 4) -#define FLITE_REG_CIODMAFMT_CBYCRY (2 << 4) -#define FLITE_REG_CIODMAFMT_CRYCBY (3 << 4) -#define FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK (0x3 << 4) - -/* Camera Output Canvas */ -#define FLITE_REG_CIOCAN 0x20 -#define FLITE_REG_CIOCAN_MASK ((0x3fff << 16) | 0x3fff) - -/* Camera Output DMA Offset */ -#define FLITE_REG_CIOOFF 0x24 -#define FLITE_REG_CIOOFF_MASK ((0x3fff << 16) | 0x3fff) - -/* Camera Output DMA Start Address */ -#define FLITE_REG_CIOSA 0x30 - -/* Camera Status */ -#define FLITE_REG_CISTATUS 0x40 -#define FLITE_REG_CISTATUS_MIPI_VVALID BIT(22) -#define FLITE_REG_CISTATUS_MIPI_HVALID BIT(21) -#define FLITE_REG_CISTATUS_MIPI_DVALID BIT(20) -#define FLITE_REG_CISTATUS_ITU_VSYNC BIT(14) -#define FLITE_REG_CISTATUS_ITU_HREFF BIT(13) -#define FLITE_REG_CISTATUS_OVFIY BIT(10) -#define FLITE_REG_CISTATUS_OVFICB BIT(9) -#define FLITE_REG_CISTATUS_OVFICR BIT(8) -#define FLITE_REG_CISTATUS_IRQ_SRC_OVERFLOW BIT(7) -#define FLITE_REG_CISTATUS_IRQ_SRC_LASTCAPEND BIT(6) -#define FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART BIT(5) -#define FLITE_REG_CISTATUS_IRQ_SRC_FRMEND BIT(4) -#define FLITE_REG_CISTATUS_IRQ_CAM BIT(0) -#define FLITE_REG_CISTATUS_IRQ_MASK (0xf << 4) - -/* Camera Status2 */ -#define FLITE_REG_CISTATUS2 0x44 -#define FLITE_REG_CISTATUS2_LASTCAPEND BIT(1) -#define FLITE_REG_CISTATUS2_FRMEND BIT(0) - -/* Qos Threshold */ -#define FLITE_REG_CITHOLD 0xf0 -#define FLITE_REG_CITHOLD_W_QOS_EN BIT(30) - -/* Camera General Purpose */ -#define FLITE_REG_CIGENERAL 0xfc -/* b0: 1 - camera B, 0 - camera A */ -#define FLITE_REG_CIGENERAL_CAM_B BIT(0) - -#define FLITE_REG_CIFCNTSEQ 0x100 -#define FLITE_REG_CIOSAN(x) (0x200 + (4 * (x))) - -/* ---------------------------------------------------------------------------- - * Function declarations - */ -void flite_hw_reset(struct fimc_lite *dev); -void flite_hw_clear_pending_irq(struct fimc_lite *dev); -u32 flite_hw_get_interrupt_source(struct fimc_lite *dev); -void flite_hw_clear_last_capture_end(struct fimc_lite *dev); -void flite_hw_set_interrupt_mask(struct fimc_lite *dev); -void flite_hw_capture_start(struct fimc_lite *dev); -void flite_hw_capture_stop(struct fimc_lite *dev); -void flite_hw_set_camera_bus(struct fimc_lite *dev, - struct fimc_source_info *s_info); -void flite_hw_set_camera_polarity(struct fimc_lite *dev, - struct fimc_source_info *cam); -void flite_hw_set_window_offset(struct fimc_lite *dev, struct flite_frame *f); -void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f); - -void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f, - bool enable); -void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f); -void flite_hw_set_test_pattern(struct fimc_lite *dev, bool on); -void flite_hw_dump_regs(struct fimc_lite *dev, const char *label); -void flite_hw_set_dma_buffer(struct fimc_lite *dev, struct flite_buffer *buf); -void flite_hw_mask_dma_buffer(struct fimc_lite *dev, u32 index); - -static inline void flite_hw_set_dma_buf_mask(struct fimc_lite *dev, u32 mask) -{ - writel(mask, dev->regs + FLITE_REG_CIFCNTSEQ); -} - -#endif /* FIMC_LITE_REG_H */ diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c deleted file mode 100644 index 2e8f476efc5c..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ /dev/null @@ -1,1673 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung EXYNOS FIMC-LITE (camera host interface) driver -* - * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. - * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> - */ -#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__ - -#include <linux/bug.h> -#include <linux/clk.h> -#include <linux/device.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/types.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.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/v4l2-rect.h> -#include <media/videobuf2-v4l2.h> -#include <media/videobuf2-dma-contig.h> -#include <media/drv-intf/exynos-fimc.h> - -#include "common.h" -#include "fimc-core.h" -#include "fimc-lite.h" -#include "fimc-lite-reg.h" - -static int debug; -module_param(debug, int, 0644); - -static const struct fimc_fmt fimc_lite_formats[] = { - { - .fourcc = V4L2_PIX_FMT_YUYV, - .colorspace = V4L2_COLORSPACE_JPEG, - .depth = { 16 }, - .color = FIMC_FMT_YCBYCR422, - .memplanes = 1, - .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, - .flags = FMT_FLAGS_YUV, - }, { - .fourcc = V4L2_PIX_FMT_UYVY, - .colorspace = V4L2_COLORSPACE_JPEG, - .depth = { 16 }, - .color = FIMC_FMT_CBYCRY422, - .memplanes = 1, - .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, - .flags = FMT_FLAGS_YUV, - }, { - .fourcc = V4L2_PIX_FMT_VYUY, - .colorspace = V4L2_COLORSPACE_JPEG, - .depth = { 16 }, - .color = FIMC_FMT_CRYCBY422, - .memplanes = 1, - .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, - .flags = FMT_FLAGS_YUV, - }, { - .fourcc = V4L2_PIX_FMT_YVYU, - .colorspace = V4L2_COLORSPACE_JPEG, - .depth = { 16 }, - .color = FIMC_FMT_YCRYCB422, - .memplanes = 1, - .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, - .flags = FMT_FLAGS_YUV, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG8, - .colorspace = V4L2_COLORSPACE_SRGB, - .depth = { 8 }, - .color = FIMC_FMT_RAW8, - .memplanes = 1, - .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, - .flags = FMT_FLAGS_RAW_BAYER, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG10, - .colorspace = V4L2_COLORSPACE_SRGB, - .depth = { 16 }, - .color = FIMC_FMT_RAW10, - .memplanes = 1, - .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, - .flags = FMT_FLAGS_RAW_BAYER, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG12, - .colorspace = V4L2_COLORSPACE_SRGB, - .depth = { 16 }, - .color = FIMC_FMT_RAW12, - .memplanes = 1, - .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, - .flags = FMT_FLAGS_RAW_BAYER, - }, -}; - -/** - * fimc_lite_find_format - lookup fimc color format by fourcc or media bus code - * @pixelformat: fourcc to match, ignored if null - * @mbus_code: media bus code to match, ignored if null - * @mask: the color format flags to match - * @index: index to the fimc_lite_formats array, ignored if negative - */ -static const struct fimc_fmt *fimc_lite_find_format(const u32 *pixelformat, - const u32 *mbus_code, unsigned int mask, int index) -{ - const struct fimc_fmt *fmt, *def_fmt = NULL; - unsigned int i; - int id = 0; - - if (index >= (int)ARRAY_SIZE(fimc_lite_formats)) - return NULL; - - for (i = 0; i < ARRAY_SIZE(fimc_lite_formats); ++i) { - fmt = &fimc_lite_formats[i]; - if (mask && !(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_lite_hw_init(struct fimc_lite *fimc, bool isp_output) -{ - struct fimc_source_info *si; - unsigned long flags; - - if (fimc->sensor == NULL) - return -ENXIO; - - if (fimc->inp_frame.fmt == NULL || fimc->out_frame.fmt == NULL) - return -EINVAL; - - /* Get sensor configuration data from the sensor subdev */ - si = v4l2_get_subdev_hostdata(fimc->sensor); - if (!si) - return -EINVAL; - - spin_lock_irqsave(&fimc->slock, flags); - - flite_hw_set_camera_bus(fimc, si); - flite_hw_set_source_format(fimc, &fimc->inp_frame); - flite_hw_set_window_offset(fimc, &fimc->inp_frame); - flite_hw_set_dma_buf_mask(fimc, 0); - flite_hw_set_output_dma(fimc, &fimc->out_frame, !isp_output); - flite_hw_set_interrupt_mask(fimc); - flite_hw_set_test_pattern(fimc, fimc->test_pattern->val); - - if (debug > 0) - flite_hw_dump_regs(fimc, __func__); - - spin_unlock_irqrestore(&fimc->slock, flags); - return 0; -} - -/* - * Reinitialize the driver so it is ready to start the streaming again. - * Set fimc->state to indicate stream off and the hardware shut down state. - * If not suspending (@suspend is false), return any buffers to videobuf2. - * Otherwise put any owned buffers onto the pending buffers queue, so they - * can be re-spun when the device is being resumed. Also perform FIMC - * software reset and disable streaming on the whole pipeline if required. - */ -static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend) -{ - struct flite_buffer *buf; - unsigned long flags; - bool streaming; - - spin_lock_irqsave(&fimc->slock, flags); - streaming = fimc->state & (1 << ST_SENSOR_STREAM); - - fimc->state &= ~(1 << ST_FLITE_RUN | 1 << ST_FLITE_OFF | - 1 << ST_FLITE_STREAM | 1 << ST_SENSOR_STREAM); - if (suspend) - fimc->state |= (1 << ST_FLITE_SUSPENDED); - else - fimc->state &= ~(1 << ST_FLITE_PENDING | - 1 << ST_FLITE_SUSPENDED); - - /* Release unused buffers */ - while (!suspend && !list_empty(&fimc->pending_buf_q)) { - buf = fimc_lite_pending_queue_pop(fimc); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } - /* If suspending put unused buffers onto pending queue */ - while (!list_empty(&fimc->active_buf_q)) { - buf = fimc_lite_active_queue_pop(fimc); - if (suspend) - fimc_lite_pending_queue_add(fimc, buf); - else - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } - - spin_unlock_irqrestore(&fimc->slock, flags); - - flite_hw_reset(fimc); - - if (!streaming) - return 0; - - return fimc_pipeline_call(&fimc->ve, set_stream, 0); -} - -static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend) -{ - unsigned long flags; - - if (!fimc_lite_active(fimc)) - return 0; - - spin_lock_irqsave(&fimc->slock, flags); - set_bit(ST_FLITE_OFF, &fimc->state); - flite_hw_capture_stop(fimc); - spin_unlock_irqrestore(&fimc->slock, flags); - - wait_event_timeout(fimc->irq_queue, - !test_bit(ST_FLITE_OFF, &fimc->state), - (2*HZ/10)); /* 200 ms */ - - return fimc_lite_reinit(fimc, suspend); -} - -/* Must be called with fimc.slock spinlock held. */ -static void fimc_lite_config_update(struct fimc_lite *fimc) -{ - flite_hw_set_window_offset(fimc, &fimc->inp_frame); - flite_hw_set_dma_window(fimc, &fimc->out_frame); - flite_hw_set_test_pattern(fimc, fimc->test_pattern->val); - clear_bit(ST_FLITE_CONFIG, &fimc->state); -} - -static irqreturn_t flite_irq_handler(int irq, void *priv) -{ - struct fimc_lite *fimc = priv; - struct flite_buffer *vbuf; - unsigned long flags; - u32 intsrc; - - spin_lock_irqsave(&fimc->slock, flags); - - intsrc = flite_hw_get_interrupt_source(fimc); - flite_hw_clear_pending_irq(fimc); - - if (test_and_clear_bit(ST_FLITE_OFF, &fimc->state)) { - wake_up(&fimc->irq_queue); - goto done; - } - - if (intsrc & FLITE_REG_CISTATUS_IRQ_SRC_OVERFLOW) { - clear_bit(ST_FLITE_RUN, &fimc->state); - fimc->events.data_overflow++; - } - - if (intsrc & FLITE_REG_CISTATUS_IRQ_SRC_LASTCAPEND) { - flite_hw_clear_last_capture_end(fimc); - clear_bit(ST_FLITE_STREAM, &fimc->state); - wake_up(&fimc->irq_queue); - } - - if (atomic_read(&fimc->out_path) != FIMC_IO_DMA) - goto done; - - if ((intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART) && - test_bit(ST_FLITE_RUN, &fimc->state) && - !list_empty(&fimc->pending_buf_q)) { - vbuf = fimc_lite_pending_queue_pop(fimc); - flite_hw_set_dma_buffer(fimc, vbuf); - fimc_lite_active_queue_add(fimc, vbuf); - } - - if ((intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMEND) && - test_bit(ST_FLITE_RUN, &fimc->state) && - !list_empty(&fimc->active_buf_q)) { - vbuf = fimc_lite_active_queue_pop(fimc); - vbuf->vb.vb2_buf.timestamp = ktime_get_ns(); - vbuf->vb.sequence = fimc->frame_count++; - flite_hw_mask_dma_buffer(fimc, vbuf->index); - vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); - } - - if (test_bit(ST_FLITE_CONFIG, &fimc->state)) - fimc_lite_config_update(fimc); - - if (list_empty(&fimc->pending_buf_q)) { - flite_hw_capture_stop(fimc); - clear_bit(ST_FLITE_STREAM, &fimc->state); - } -done: - set_bit(ST_FLITE_RUN, &fimc->state); - spin_unlock_irqrestore(&fimc->slock, flags); - return IRQ_HANDLED; -} - -static int start_streaming(struct vb2_queue *q, unsigned int count) -{ - struct fimc_lite *fimc = q->drv_priv; - unsigned long flags; - int ret; - - spin_lock_irqsave(&fimc->slock, flags); - - fimc->buf_index = 0; - fimc->frame_count = 0; - - spin_unlock_irqrestore(&fimc->slock, flags); - - ret = fimc_lite_hw_init(fimc, false); - if (ret) { - fimc_lite_reinit(fimc, false); - return ret; - } - - set_bit(ST_FLITE_PENDING, &fimc->state); - - if (!list_empty(&fimc->active_buf_q) && - !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) { - flite_hw_capture_start(fimc); - - if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) - fimc_pipeline_call(&fimc->ve, set_stream, 1); - } - if (debug > 0) - flite_hw_dump_regs(fimc, __func__); - - return 0; -} - -static void stop_streaming(struct vb2_queue *q) -{ - struct fimc_lite *fimc = q->drv_priv; - - if (!fimc_lite_active(fimc)) - return; - - fimc_lite_stop_capture(fimc, false); -} - -static int queue_setup(struct vb2_queue *vq, - unsigned int *num_buffers, unsigned int *num_planes, - unsigned int sizes[], struct device *alloc_devs[]) -{ - struct fimc_lite *fimc = vq->drv_priv; - struct flite_frame *frame = &fimc->out_frame; - const struct fimc_fmt *fmt = frame->fmt; - unsigned long wh = frame->f_width * frame->f_height; - int i; - - if (fmt == NULL) - return -EINVAL; - - if (*num_planes) { - if (*num_planes != fmt->memplanes) - return -EINVAL; - for (i = 0; i < *num_planes; i++) - if (sizes[i] < (wh * fmt->depth[i]) / 8) - return -EINVAL; - return 0; - } - - *num_planes = fmt->memplanes; - - for (i = 0; i < fmt->memplanes; i++) - sizes[i] = (wh * fmt->depth[i]) / 8; - - return 0; -} - -static int buffer_prepare(struct vb2_buffer *vb) -{ - struct vb2_queue *vq = vb->vb2_queue; - struct fimc_lite *fimc = vq->drv_priv; - int i; - - if (fimc->out_frame.fmt == NULL) - return -EINVAL; - - for (i = 0; i < fimc->out_frame.fmt->memplanes; i++) { - unsigned long size = fimc->payload[i]; - - if (vb2_plane_size(vb, i) < size) { - v4l2_err(&fimc->ve.vdev, - "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 vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct flite_buffer *buf - = container_of(vbuf, struct flite_buffer, vb); - struct fimc_lite *fimc = vb2_get_drv_priv(vb->vb2_queue); - unsigned long flags; - - spin_lock_irqsave(&fimc->slock, flags); - buf->addr = vb2_dma_contig_plane_dma_addr(vb, 0); - - buf->index = fimc->buf_index++; - if (fimc->buf_index >= fimc->reqbufs_count) - fimc->buf_index = 0; - - if (!test_bit(ST_FLITE_SUSPENDED, &fimc->state) && - !test_bit(ST_FLITE_STREAM, &fimc->state) && - list_empty(&fimc->active_buf_q)) { - flite_hw_set_dma_buffer(fimc, buf); - fimc_lite_active_queue_add(fimc, buf); - } else { - fimc_lite_pending_queue_add(fimc, buf); - } - - if (vb2_is_streaming(&fimc->vb_queue) && - !list_empty(&fimc->pending_buf_q) && - !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) { - flite_hw_capture_start(fimc); - spin_unlock_irqrestore(&fimc->slock, flags); - - if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) - fimc_pipeline_call(&fimc->ve, set_stream, 1); - return; - } - spin_unlock_irqrestore(&fimc->slock, flags); -} - -static const struct vb2_ops fimc_lite_qops = { - .queue_setup = queue_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .start_streaming = start_streaming, - .stop_streaming = stop_streaming, -}; - -static void fimc_lite_clear_event_counters(struct fimc_lite *fimc) -{ - unsigned long flags; - - spin_lock_irqsave(&fimc->slock, flags); - memset(&fimc->events, 0, sizeof(fimc->events)); - spin_unlock_irqrestore(&fimc->slock, flags); -} - -static int fimc_lite_open(struct file *file) -{ - struct fimc_lite *fimc = video_drvdata(file); - struct media_entity *me = &fimc->ve.vdev.entity; - int ret; - - mutex_lock(&fimc->lock); - if (atomic_read(&fimc->out_path) != FIMC_IO_DMA) { - ret = -EBUSY; - goto unlock; - } - - set_bit(ST_FLITE_IN_USE, &fimc->state); - ret = pm_runtime_resume_and_get(&fimc->pdev->dev); - if (ret < 0) - goto err_in_use; - - ret = v4l2_fh_open(file); - if (ret < 0) - goto err_pm; - - if (!v4l2_fh_is_singular_file(file) || - atomic_read(&fimc->out_path) != FIMC_IO_DMA) - goto unlock; - - mutex_lock(&me->graph_obj.mdev->graph_mutex); - - ret = fimc_pipeline_call(&fimc->ve, open, me, true); - - /* Mark video pipeline ending at this video node as in use. */ - if (ret == 0) - me->use_count++; - - mutex_unlock(&me->graph_obj.mdev->graph_mutex); - - if (!ret) { - fimc_lite_clear_event_counters(fimc); - goto unlock; - } - - v4l2_fh_release(file); -err_pm: - pm_runtime_put_sync(&fimc->pdev->dev); -err_in_use: - clear_bit(ST_FLITE_IN_USE, &fimc->state); -unlock: - mutex_unlock(&fimc->lock); - return ret; -} - -static int fimc_lite_release(struct file *file) -{ - struct fimc_lite *fimc = video_drvdata(file); - struct media_entity *entity = &fimc->ve.vdev.entity; - - mutex_lock(&fimc->lock); - - if (v4l2_fh_is_singular_file(file) && - atomic_read(&fimc->out_path) == FIMC_IO_DMA) { - if (fimc->streaming) { - media_pipeline_stop(entity); - fimc->streaming = false; - } - fimc_lite_stop_capture(fimc, false); - fimc_pipeline_call(&fimc->ve, close); - clear_bit(ST_FLITE_IN_USE, &fimc->state); - - mutex_lock(&entity->graph_obj.mdev->graph_mutex); - entity->use_count--; - mutex_unlock(&entity->graph_obj.mdev->graph_mutex); - } - - _vb2_fop_release(file, NULL); - pm_runtime_put(&fimc->pdev->dev); - clear_bit(ST_FLITE_SUSPENDED, &fimc->state); - - mutex_unlock(&fimc->lock); - return 0; -} - -static const struct v4l2_file_operations fimc_lite_fops = { - .owner = THIS_MODULE, - .open = fimc_lite_open, - .release = fimc_lite_release, - .poll = vb2_fop_poll, - .unlocked_ioctl = video_ioctl2, - .mmap = vb2_fop_mmap, -}; - -/* - * Format and crop negotiation helpers - */ - -static const struct fimc_fmt *fimc_lite_subdev_try_fmt(struct fimc_lite *fimc, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) -{ - struct flite_drvdata *dd = fimc->dd; - struct v4l2_mbus_framefmt *mf = &format->format; - const struct fimc_fmt *fmt = NULL; - - if (format->pad == FLITE_SD_PAD_SINK) { - v4l_bound_align_image(&mf->width, 8, dd->max_width, - ffs(dd->out_width_align) - 1, - &mf->height, 0, dd->max_height, 0, 0); - - fmt = fimc_lite_find_format(NULL, &mf->code, 0, 0); - if (WARN_ON(!fmt)) - return NULL; - - mf->colorspace = fmt->colorspace; - mf->code = fmt->mbus_code; - } else { - struct flite_frame *sink = &fimc->inp_frame; - struct v4l2_mbus_framefmt *sink_fmt; - struct v4l2_rect *rect; - - if (format->which == V4L2_SUBDEV_FORMAT_TRY) { - sink_fmt = v4l2_subdev_get_try_format(&fimc->subdev, - sd_state, - FLITE_SD_PAD_SINK); - - mf->code = sink_fmt->code; - mf->colorspace = sink_fmt->colorspace; - - rect = v4l2_subdev_get_try_crop(&fimc->subdev, - sd_state, - FLITE_SD_PAD_SINK); - } else { - mf->code = sink->fmt->mbus_code; - mf->colorspace = sink->fmt->colorspace; - rect = &sink->rect; - } - - /* Allow changing format only on sink pad */ - mf->width = rect->width; - mf->height = rect->height; - } - - mf->field = V4L2_FIELD_NONE; - - v4l2_dbg(1, debug, &fimc->subdev, "code: %#x (%d), %dx%d\n", - mf->code, mf->colorspace, mf->width, mf->height); - - return fmt; -} - -static void fimc_lite_try_crop(struct fimc_lite *fimc, struct v4l2_rect *r) -{ - struct flite_frame *frame = &fimc->inp_frame; - - v4l_bound_align_image(&r->width, 0, frame->f_width, 0, - &r->height, 0, frame->f_height, 0, 0); - - /* Adjust left/top if cropping rectangle got out of bounds */ - r->left = clamp_t(u32, r->left, 0, frame->f_width - r->width); - r->left = round_down(r->left, fimc->dd->win_hor_offs_align); - r->top = clamp_t(u32, r->top, 0, frame->f_height - r->height); - - v4l2_dbg(1, debug, &fimc->subdev, "(%d,%d)/%dx%d, sink fmt: %dx%d\n", - r->left, r->top, r->width, r->height, - frame->f_width, frame->f_height); -} - -static void fimc_lite_try_compose(struct fimc_lite *fimc, struct v4l2_rect *r) -{ - struct flite_frame *frame = &fimc->out_frame; - struct v4l2_rect *crop_rect = &fimc->inp_frame.rect; - - /* Scaling is not supported so we enforce compose rectangle size - same as size of the sink crop rectangle. */ - r->width = crop_rect->width; - r->height = crop_rect->height; - - /* Adjust left/top if the composing rectangle got out of bounds */ - r->left = clamp_t(u32, r->left, 0, frame->f_width - r->width); - r->left = round_down(r->left, fimc->dd->out_hor_offs_align); - r->top = clamp_t(u32, r->top, 0, fimc->out_frame.f_height - r->height); - - v4l2_dbg(1, debug, &fimc->subdev, "(%d,%d)/%dx%d, source fmt: %dx%d\n", - r->left, r->top, r->width, r->height, - frame->f_width, frame->f_height); -} - -/* - * Video node ioctl operations - */ -static int fimc_lite_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct fimc_lite *fimc = video_drvdata(file); - - strscpy(cap->driver, FIMC_LITE_DRV_NAME, sizeof(cap->driver)); - strscpy(cap->card, FIMC_LITE_DRV_NAME, sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", - dev_name(&fimc->pdev->dev)); - return 0; -} - -static int fimc_lite_enum_fmt(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - const struct fimc_fmt *fmt; - - if (f->index >= ARRAY_SIZE(fimc_lite_formats)) - return -EINVAL; - - fmt = &fimc_lite_formats[f->index]; - f->pixelformat = fmt->fourcc; - - return 0; -} - -static int fimc_lite_g_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct fimc_lite *fimc = video_drvdata(file); - struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; - struct v4l2_plane_pix_format *plane_fmt = &pixm->plane_fmt[0]; - struct flite_frame *frame = &fimc->out_frame; - const struct fimc_fmt *fmt = frame->fmt; - - plane_fmt->bytesperline = (frame->f_width * fmt->depth[0]) / 8; - plane_fmt->sizeimage = plane_fmt->bytesperline * frame->f_height; - - pixm->num_planes = fmt->memplanes; - pixm->pixelformat = fmt->fourcc; - pixm->width = frame->f_width; - pixm->height = frame->f_height; - pixm->field = V4L2_FIELD_NONE; - pixm->colorspace = fmt->colorspace; - return 0; -} - -static int fimc_lite_try_fmt(struct fimc_lite *fimc, - struct v4l2_pix_format_mplane *pixm, - const struct fimc_fmt **ffmt) -{ - u32 bpl = pixm->plane_fmt[0].bytesperline; - struct flite_drvdata *dd = fimc->dd; - const struct fimc_fmt *inp_fmt = fimc->inp_frame.fmt; - const struct fimc_fmt *fmt; - - if (WARN_ON(inp_fmt == NULL)) - return -EINVAL; - /* - * We allow some flexibility only for YUV formats. In case of raw - * raw Bayer the FIMC-LITE's output format must match its camera - * interface input format. - */ - if (inp_fmt->flags & FMT_FLAGS_YUV) - fmt = fimc_lite_find_format(&pixm->pixelformat, NULL, - inp_fmt->flags, 0); - else - fmt = inp_fmt; - - if (WARN_ON(fmt == NULL)) - return -EINVAL; - if (ffmt) - *ffmt = fmt; - v4l_bound_align_image(&pixm->width, 8, dd->max_width, - ffs(dd->out_width_align) - 1, - &pixm->height, 0, dd->max_height, 0, 0); - - if ((bpl == 0 || ((bpl * 8) / fmt->depth[0]) < pixm->width)) - pixm->plane_fmt[0].bytesperline = (pixm->width * - fmt->depth[0]) / 8; - - if (pixm->plane_fmt[0].sizeimage == 0) - pixm->plane_fmt[0].sizeimage = (pixm->width * pixm->height * - fmt->depth[0]) / 8; - pixm->num_planes = fmt->memplanes; - pixm->pixelformat = fmt->fourcc; - pixm->colorspace = fmt->colorspace; - pixm->field = V4L2_FIELD_NONE; - return 0; -} - -static int fimc_lite_try_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct fimc_lite *fimc = video_drvdata(file); - return fimc_lite_try_fmt(fimc, &f->fmt.pix_mp, NULL); -} - -static int fimc_lite_s_fmt_mplane(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; - struct fimc_lite *fimc = video_drvdata(file); - struct flite_frame *frame = &fimc->out_frame; - const struct fimc_fmt *fmt = NULL; - int ret; - - if (vb2_is_busy(&fimc->vb_queue)) - return -EBUSY; - - ret = fimc_lite_try_fmt(fimc, &f->fmt.pix_mp, &fmt); - if (ret < 0) - return ret; - - frame->fmt = fmt; - fimc->payload[0] = max((pixm->width * pixm->height * fmt->depth[0]) / 8, - pixm->plane_fmt[0].sizeimage); - frame->f_width = pixm->width; - frame->f_height = pixm->height; - - return 0; -} - -static int fimc_pipeline_validate(struct fimc_lite *fimc) -{ - struct v4l2_subdev *sd = &fimc->subdev; - struct v4l2_subdev_format sink_fmt, src_fmt; - struct media_pad *pad; - int ret; - - 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->subdev) { - struct flite_frame *ff = &fimc->out_frame; - sink_fmt.format.width = ff->f_width; - sink_fmt.format.height = ff->f_height; - sink_fmt.format.code = fimc->inp_frame.fmt->mbus_code; - } 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_pad(pad); - if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) - 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_lite_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct fimc_lite *fimc = video_drvdata(file); - struct media_entity *entity = &fimc->ve.vdev.entity; - int ret; - - if (fimc_lite_active(fimc)) - return -EBUSY; - - ret = media_pipeline_start(entity, &fimc->ve.pipe->mp); - if (ret < 0) - return ret; - - ret = fimc_pipeline_validate(fimc); - if (ret < 0) - goto err_p_stop; - - fimc->sensor = fimc_find_remote_sensor(&fimc->subdev.entity); - - ret = vb2_ioctl_streamon(file, priv, type); - if (!ret) { - fimc->streaming = true; - return ret; - } - -err_p_stop: - media_pipeline_stop(entity); - return 0; -} - -static int fimc_lite_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct fimc_lite *fimc = video_drvdata(file); - int ret; - - ret = vb2_ioctl_streamoff(file, priv, type); - if (ret < 0) - return ret; - - media_pipeline_stop(&fimc->ve.vdev.entity); - fimc->streaming = false; - return 0; -} - -static int fimc_lite_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) -{ - struct fimc_lite *fimc = video_drvdata(file); - int ret; - - reqbufs->count = max_t(u32, FLITE_REQ_BUFS_MIN, reqbufs->count); - ret = vb2_ioctl_reqbufs(file, priv, reqbufs); - if (!ret) - fimc->reqbufs_count = reqbufs->count; - - return ret; -} - -static int fimc_lite_g_selection(struct file *file, void *fh, - struct v4l2_selection *sel) -{ - struct fimc_lite *fimc = video_drvdata(file); - struct flite_frame *f = &fimc->out_frame; - - if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - switch (sel->target) { - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - sel->r.left = 0; - sel->r.top = 0; - sel->r.width = f->f_width; - sel->r.height = f->f_height; - return 0; - - case V4L2_SEL_TGT_COMPOSE: - sel->r = f->rect; - return 0; - } - - return -EINVAL; -} - -static int fimc_lite_s_selection(struct file *file, void *fh, - struct v4l2_selection *sel) -{ - struct fimc_lite *fimc = video_drvdata(file); - struct flite_frame *f = &fimc->out_frame; - struct v4l2_rect rect = sel->r; - unsigned long flags; - - if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - sel->target != V4L2_SEL_TGT_COMPOSE) - return -EINVAL; - - fimc_lite_try_compose(fimc, &rect); - - if ((sel->flags & V4L2_SEL_FLAG_LE) && - !v4l2_rect_enclosed(&rect, &sel->r)) - return -ERANGE; - - if ((sel->flags & V4L2_SEL_FLAG_GE) && - !v4l2_rect_enclosed(&sel->r, &rect)) - return -ERANGE; - - sel->r = rect; - spin_lock_irqsave(&fimc->slock, flags); - f->rect = rect; - set_bit(ST_FLITE_CONFIG, &fimc->state); - spin_unlock_irqrestore(&fimc->slock, flags); - - return 0; -} - -static const struct v4l2_ioctl_ops fimc_lite_ioctl_ops = { - .vidioc_querycap = fimc_lite_querycap, - .vidioc_enum_fmt_vid_cap = fimc_lite_enum_fmt, - .vidioc_try_fmt_vid_cap_mplane = fimc_lite_try_fmt_mplane, - .vidioc_s_fmt_vid_cap_mplane = fimc_lite_s_fmt_mplane, - .vidioc_g_fmt_vid_cap_mplane = fimc_lite_g_fmt_mplane, - .vidioc_g_selection = fimc_lite_g_selection, - .vidioc_s_selection = fimc_lite_s_selection, - .vidioc_reqbufs = fimc_lite_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_streamon = fimc_lite_streamon, - .vidioc_streamoff = fimc_lite_streamoff, -}; - -/* Capture subdev media entity operations */ -static int fimc_lite_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_lite *fimc = v4l2_get_subdevdata(sd); - int ret = 0; - - if (WARN_ON(fimc == NULL)) - return 0; - - v4l2_dbg(1, debug, sd, "%s: %s --> %s, flags: 0x%x. source_id: 0x%x\n", - __func__, remote->entity->name, local->entity->name, - flags, fimc->source_subdev_grp_id); - - switch (local->index) { - case FLITE_SD_PAD_SINK: - if (flags & MEDIA_LNK_FL_ENABLED) { - if (fimc->source_subdev_grp_id == 0) - fimc->source_subdev_grp_id = sd->grp_id; - else - ret = -EBUSY; - } else { - fimc->source_subdev_grp_id = 0; - fimc->sensor = NULL; - } - break; - - case FLITE_SD_PAD_SOURCE_DMA: - if (!(flags & MEDIA_LNK_FL_ENABLED)) - atomic_set(&fimc->out_path, FIMC_IO_NONE); - else - atomic_set(&fimc->out_path, FIMC_IO_DMA); - break; - - case FLITE_SD_PAD_SOURCE_ISP: - if (!(flags & MEDIA_LNK_FL_ENABLED)) - atomic_set(&fimc->out_path, FIMC_IO_NONE); - else - atomic_set(&fimc->out_path, FIMC_IO_ISP); - break; - - default: - v4l2_err(sd, "Invalid pad index\n"); - ret = -EINVAL; - } - mb(); - - return ret; -} - -static const struct media_entity_operations fimc_lite_subdev_media_ops = { - .link_setup = fimc_lite_link_setup, -}; - -static int fimc_lite_subdev_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - const struct fimc_fmt *fmt; - - fmt = fimc_lite_find_format(NULL, NULL, 0, code->index); - if (!fmt) - return -EINVAL; - code->code = fmt->mbus_code; - return 0; -} - -static struct v4l2_mbus_framefmt *__fimc_lite_subdev_get_try_fmt( - struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, unsigned int pad) -{ - if (pad != FLITE_SD_PAD_SINK) - pad = FLITE_SD_PAD_SOURCE_DMA; - - return v4l2_subdev_get_try_format(sd, sd_state, pad); -} - -static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct fimc_lite *fimc = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *mf = &fmt->format; - struct flite_frame *f = &fimc->inp_frame; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = __fimc_lite_subdev_get_try_fmt(sd, sd_state, fmt->pad); - fmt->format = *mf; - return 0; - } - - mutex_lock(&fimc->lock); - mf->colorspace = f->fmt->colorspace; - mf->code = f->fmt->mbus_code; - - if (fmt->pad == FLITE_SD_PAD_SINK) { - /* full camera input frame size */ - mf->width = f->f_width; - mf->height = f->f_height; - } else { - /* crop size */ - mf->width = f->rect.width; - mf->height = f->rect.height; - } - mutex_unlock(&fimc->lock); - return 0; -} - -static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct fimc_lite *fimc = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *mf = &fmt->format; - struct flite_frame *sink = &fimc->inp_frame; - struct flite_frame *source = &fimc->out_frame; - const struct fimc_fmt *ffmt; - - v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %dx%d\n", - fmt->pad, mf->code, mf->width, mf->height); - - mutex_lock(&fimc->lock); - - if ((atomic_read(&fimc->out_path) == FIMC_IO_ISP && - media_entity_is_streaming(&sd->entity)) || - (atomic_read(&fimc->out_path) == FIMC_IO_DMA && - vb2_is_busy(&fimc->vb_queue))) { - mutex_unlock(&fimc->lock); - return -EBUSY; - } - - ffmt = fimc_lite_subdev_try_fmt(fimc, sd_state, fmt); - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - struct v4l2_mbus_framefmt *src_fmt; - - mf = __fimc_lite_subdev_get_try_fmt(sd, sd_state, fmt->pad); - *mf = fmt->format; - - if (fmt->pad == FLITE_SD_PAD_SINK) { - unsigned int pad = FLITE_SD_PAD_SOURCE_DMA; - src_fmt = __fimc_lite_subdev_get_try_fmt(sd, sd_state, - pad); - *src_fmt = *mf; - } - - mutex_unlock(&fimc->lock); - return 0; - } - - if (fmt->pad == FLITE_SD_PAD_SINK) { - sink->f_width = mf->width; - sink->f_height = mf->height; - sink->fmt = ffmt; - /* Set sink crop rectangle */ - sink->rect.width = mf->width; - sink->rect.height = mf->height; - sink->rect.left = 0; - sink->rect.top = 0; - /* Reset source format and crop rectangle */ - source->rect = sink->rect; - source->f_width = mf->width; - source->f_height = mf->height; - } - - mutex_unlock(&fimc->lock); - return 0; -} - -static int fimc_lite_subdev_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_selection *sel) -{ - struct fimc_lite *fimc = v4l2_get_subdevdata(sd); - struct flite_frame *f = &fimc->inp_frame; - - if ((sel->target != V4L2_SEL_TGT_CROP && - sel->target != V4L2_SEL_TGT_CROP_BOUNDS) || - sel->pad != FLITE_SD_PAD_SINK) - return -EINVAL; - - if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { - sel->r = *v4l2_subdev_get_try_crop(sd, sd_state, sel->pad); - return 0; - } - - mutex_lock(&fimc->lock); - if (sel->target == V4L2_SEL_TGT_CROP) { - sel->r = f->rect; - } else { - sel->r.left = 0; - sel->r.top = 0; - sel->r.width = f->f_width; - sel->r.height = f->f_height; - } - mutex_unlock(&fimc->lock); - - v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %d, f_h: %d\n", - __func__, f->rect.left, f->rect.top, f->rect.width, - f->rect.height, f->f_width, f->f_height); - - return 0; -} - -static int fimc_lite_subdev_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_selection *sel) -{ - struct fimc_lite *fimc = v4l2_get_subdevdata(sd); - struct flite_frame *f = &fimc->inp_frame; - int ret = 0; - - if (sel->target != V4L2_SEL_TGT_CROP || sel->pad != FLITE_SD_PAD_SINK) - return -EINVAL; - - mutex_lock(&fimc->lock); - fimc_lite_try_crop(fimc, &sel->r); - - if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { - *v4l2_subdev_get_try_crop(sd, sd_state, sel->pad) = sel->r; - } else { - unsigned long flags; - spin_lock_irqsave(&fimc->slock, flags); - f->rect = sel->r; - /* Same crop rectangle on the source pad */ - fimc->out_frame.rect = sel->r; - set_bit(ST_FLITE_CONFIG, &fimc->state); - spin_unlock_irqrestore(&fimc->slock, flags); - } - mutex_unlock(&fimc->lock); - - v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %d, f_h: %d\n", - __func__, f->rect.left, f->rect.top, f->rect.width, - f->rect.height, f->f_width, f->f_height); - - return ret; -} - -static int fimc_lite_subdev_s_stream(struct v4l2_subdev *sd, int on) -{ - struct fimc_lite *fimc = v4l2_get_subdevdata(sd); - unsigned long flags; - int ret; - - /* - * Find sensor subdev linked to FIMC-LITE directly or through - * MIPI-CSIS. This is required for configuration where FIMC-LITE - * is used as a subdev only and feeds data internally to FIMC-IS. - * The pipeline links are protected through entity.pipe so there is no - * need to take the media graph mutex here. - */ - fimc->sensor = fimc_find_remote_sensor(&sd->entity); - - if (atomic_read(&fimc->out_path) != FIMC_IO_ISP) - return -ENOIOCTLCMD; - - mutex_lock(&fimc->lock); - if (on) { - flite_hw_reset(fimc); - ret = fimc_lite_hw_init(fimc, true); - if (!ret) { - spin_lock_irqsave(&fimc->slock, flags); - flite_hw_capture_start(fimc); - spin_unlock_irqrestore(&fimc->slock, flags); - } - } else { - set_bit(ST_FLITE_OFF, &fimc->state); - - spin_lock_irqsave(&fimc->slock, flags); - flite_hw_capture_stop(fimc); - spin_unlock_irqrestore(&fimc->slock, flags); - - ret = wait_event_timeout(fimc->irq_queue, - !test_bit(ST_FLITE_OFF, &fimc->state), - msecs_to_jiffies(200)); - if (ret == 0) - v4l2_err(sd, "s_stream(0) timeout\n"); - clear_bit(ST_FLITE_RUN, &fimc->state); - } - - mutex_unlock(&fimc->lock); - return ret; -} - -static int fimc_lite_log_status(struct v4l2_subdev *sd) -{ - struct fimc_lite *fimc = v4l2_get_subdevdata(sd); - - flite_hw_dump_regs(fimc, __func__); - return 0; -} - -static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) -{ - struct fimc_lite *fimc = v4l2_get_subdevdata(sd); - struct vb2_queue *q = &fimc->vb_queue; - struct video_device *vfd = &fimc->ve.vdev; - int ret; - - memset(vfd, 0, sizeof(*vfd)); - atomic_set(&fimc->out_path, FIMC_IO_DMA); - - snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture", - fimc->index); - - vfd->fops = &fimc_lite_fops; - vfd->ioctl_ops = &fimc_lite_ioctl_ops; - vfd->v4l2_dev = sd->v4l2_dev; - vfd->minor = -1; - vfd->release = video_device_release_empty; - vfd->queue = q; - vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING; - fimc->reqbufs_count = 0; - - INIT_LIST_HEAD(&fimc->pending_buf_q); - INIT_LIST_HEAD(&fimc->active_buf_q); - - memset(q, 0, sizeof(*q)); - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - q->io_modes = VB2_MMAP | VB2_USERPTR; - q->ops = &fimc_lite_qops; - q->mem_ops = &vb2_dma_contig_memops; - q->buf_struct_size = sizeof(struct flite_buffer); - q->drv_priv = fimc; - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &fimc->lock; - q->dev = &fimc->pdev->dev; - - ret = vb2_queue_init(q); - if (ret < 0) - return ret; - - fimc->vd_pad.flags = MEDIA_PAD_FL_SINK; - ret = media_entity_pads_init(&vfd->entity, 1, &fimc->vd_pad); - if (ret < 0) - return ret; - - video_set_drvdata(vfd, fimc); - fimc->ve.pipe = v4l2_get_subdev_hostdata(sd); - - ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); - if (ret < 0) { - media_entity_cleanup(&vfd->entity); - fimc->ve.pipe = NULL; - return ret; - } - - v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n", - vfd->name, video_device_node_name(vfd)); - return 0; -} - -static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd) -{ - struct fimc_lite *fimc = v4l2_get_subdevdata(sd); - - if (fimc == NULL) - return; - - mutex_lock(&fimc->lock); - - if (video_is_registered(&fimc->ve.vdev)) { - video_unregister_device(&fimc->ve.vdev); - media_entity_cleanup(&fimc->ve.vdev.entity); - fimc->ve.pipe = NULL; - } - - mutex_unlock(&fimc->lock); -} - -static const struct v4l2_subdev_internal_ops fimc_lite_subdev_internal_ops = { - .registered = fimc_lite_subdev_registered, - .unregistered = fimc_lite_subdev_unregistered, -}; - -static const struct v4l2_subdev_pad_ops fimc_lite_subdev_pad_ops = { - .enum_mbus_code = fimc_lite_subdev_enum_mbus_code, - .get_selection = fimc_lite_subdev_get_selection, - .set_selection = fimc_lite_subdev_set_selection, - .get_fmt = fimc_lite_subdev_get_fmt, - .set_fmt = fimc_lite_subdev_set_fmt, -}; - -static const struct v4l2_subdev_video_ops fimc_lite_subdev_video_ops = { - .s_stream = fimc_lite_subdev_s_stream, -}; - -static const struct v4l2_subdev_core_ops fimc_lite_core_ops = { - .log_status = fimc_lite_log_status, -}; - -static const struct v4l2_subdev_ops fimc_lite_subdev_ops = { - .core = &fimc_lite_core_ops, - .video = &fimc_lite_subdev_video_ops, - .pad = &fimc_lite_subdev_pad_ops, -}; - -static int fimc_lite_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct fimc_lite *fimc = container_of(ctrl->handler, struct fimc_lite, - ctrl_handler); - set_bit(ST_FLITE_CONFIG, &fimc->state); - return 0; -} - -static const struct v4l2_ctrl_ops fimc_lite_ctrl_ops = { - .s_ctrl = fimc_lite_s_ctrl, -}; - -static const struct v4l2_ctrl_config fimc_lite_ctrl = { - .ops = &fimc_lite_ctrl_ops, - .id = V4L2_CTRL_CLASS_USER | 0x1001, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Test Pattern 640x480", - .step = 1, -}; - -static void fimc_lite_set_default_config(struct fimc_lite *fimc) -{ - struct flite_frame *sink = &fimc->inp_frame; - struct flite_frame *source = &fimc->out_frame; - - sink->fmt = &fimc_lite_formats[0]; - sink->f_width = FLITE_DEFAULT_WIDTH; - sink->f_height = FLITE_DEFAULT_HEIGHT; - - sink->rect.width = FLITE_DEFAULT_WIDTH; - sink->rect.height = FLITE_DEFAULT_HEIGHT; - sink->rect.left = 0; - sink->rect.top = 0; - - *source = *sink; -} - -static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc) -{ - struct v4l2_ctrl_handler *handler = &fimc->ctrl_handler; - struct v4l2_subdev *sd = &fimc->subdev; - int ret; - - v4l2_subdev_init(sd, &fimc_lite_subdev_ops); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - snprintf(sd->name, sizeof(sd->name), "FIMC-LITE.%d", fimc->index); - - fimc->subdev_pads[FLITE_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - fimc->subdev_pads[FLITE_SD_PAD_SOURCE_DMA].flags = MEDIA_PAD_FL_SOURCE; - fimc->subdev_pads[FLITE_SD_PAD_SOURCE_ISP].flags = MEDIA_PAD_FL_SOURCE; - ret = media_entity_pads_init(&sd->entity, FLITE_SD_PADS_NUM, - fimc->subdev_pads); - if (ret) - return ret; - - v4l2_ctrl_handler_init(handler, 1); - fimc->test_pattern = v4l2_ctrl_new_custom(handler, &fimc_lite_ctrl, - NULL); - if (handler->error) { - media_entity_cleanup(&sd->entity); - return handler->error; - } - - sd->ctrl_handler = handler; - sd->internal_ops = &fimc_lite_subdev_internal_ops; - sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; - sd->entity.ops = &fimc_lite_subdev_media_ops; - sd->owner = THIS_MODULE; - v4l2_set_subdevdata(sd, fimc); - - return 0; -} - -static void fimc_lite_unregister_capture_subdev(struct fimc_lite *fimc) -{ - struct v4l2_subdev *sd = &fimc->subdev; - - v4l2_device_unregister_subdev(sd); - media_entity_cleanup(&sd->entity); - v4l2_ctrl_handler_free(&fimc->ctrl_handler); - v4l2_set_subdevdata(sd, NULL); -} - -static void fimc_lite_clk_put(struct fimc_lite *fimc) -{ - if (IS_ERR(fimc->clock)) - return; - - clk_put(fimc->clock); - fimc->clock = ERR_PTR(-EINVAL); -} - -static int fimc_lite_clk_get(struct fimc_lite *fimc) -{ - fimc->clock = clk_get(&fimc->pdev->dev, FLITE_CLK_NAME); - return PTR_ERR_OR_ZERO(fimc->clock); -} - -static const struct of_device_id flite_of_match[]; - -static int fimc_lite_probe(struct platform_device *pdev) -{ - struct flite_drvdata *drv_data = NULL; - struct device *dev = &pdev->dev; - const struct of_device_id *of_id; - struct fimc_lite *fimc; - struct resource *res; - int ret; - int irq; - - if (!dev->of_node) - return -ENODEV; - - fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL); - if (!fimc) - return -ENOMEM; - - of_id = of_match_node(flite_of_match, dev->of_node); - if (of_id) - drv_data = (struct flite_drvdata *)of_id->data; - fimc->index = of_alias_get_id(dev->of_node, "fimc-lite"); - - if (!drv_data || fimc->index >= drv_data->num_instances || - fimc->index < 0) { - dev_err(dev, "Wrong %pOF node alias\n", dev->of_node); - return -EINVAL; - } - - fimc->dd = drv_data; - fimc->pdev = pdev; - - 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_ioremap_resource(dev, res); - if (IS_ERR(fimc->regs)) - return PTR_ERR(fimc->regs); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - ret = fimc_lite_clk_get(fimc); - if (ret) - return ret; - - ret = devm_request_irq(dev, irq, flite_irq_handler, - 0, dev_name(dev), fimc); - if (ret) { - dev_err(dev, "Failed to install irq (%d)\n", ret); - goto err_clk_put; - } - - /* The video node will be created within the subdev's registered() op */ - ret = fimc_lite_create_capture_subdev(fimc); - if (ret) - goto err_clk_put; - - platform_set_drvdata(pdev, fimc); - pm_runtime_enable(dev); - - if (!pm_runtime_enabled(dev)) { - ret = clk_prepare_enable(fimc->clock); - if (ret < 0) - goto err_sd; - } - - vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); - - fimc_lite_set_default_config(fimc); - - dev_dbg(dev, "FIMC-LITE.%d registered successfully\n", - fimc->index); - return 0; - -err_sd: - fimc_lite_unregister_capture_subdev(fimc); -err_clk_put: - fimc_lite_clk_put(fimc); - return ret; -} - -#ifdef CONFIG_PM -static int fimc_lite_runtime_resume(struct device *dev) -{ - struct fimc_lite *fimc = dev_get_drvdata(dev); - - clk_prepare_enable(fimc->clock); - return 0; -} - -static int fimc_lite_runtime_suspend(struct device *dev) -{ - struct fimc_lite *fimc = dev_get_drvdata(dev); - - clk_disable_unprepare(fimc->clock); - return 0; -} -#endif - -#ifdef CONFIG_PM_SLEEP -static int fimc_lite_resume(struct device *dev) -{ - struct fimc_lite *fimc = dev_get_drvdata(dev); - struct flite_buffer *buf; - unsigned long flags; - int i; - - spin_lock_irqsave(&fimc->slock, flags); - if (!test_and_clear_bit(ST_LPM, &fimc->state) || - !test_bit(ST_FLITE_IN_USE, &fimc->state)) { - spin_unlock_irqrestore(&fimc->slock, flags); - return 0; - } - flite_hw_reset(fimc); - spin_unlock_irqrestore(&fimc->slock, flags); - - if (!test_and_clear_bit(ST_FLITE_SUSPENDED, &fimc->state)) - return 0; - - INIT_LIST_HEAD(&fimc->active_buf_q); - fimc_pipeline_call(&fimc->ve, open, - &fimc->ve.vdev.entity, false); - fimc_lite_hw_init(fimc, atomic_read(&fimc->out_path) == FIMC_IO_ISP); - clear_bit(ST_FLITE_SUSPENDED, &fimc->state); - - for (i = 0; i < fimc->reqbufs_count; i++) { - if (list_empty(&fimc->pending_buf_q)) - break; - buf = fimc_lite_pending_queue_pop(fimc); - buffer_queue(&buf->vb.vb2_buf); - } - return 0; -} - -static int fimc_lite_suspend(struct device *dev) -{ - struct fimc_lite *fimc = dev_get_drvdata(dev); - bool suspend = test_bit(ST_FLITE_IN_USE, &fimc->state); - int ret; - - if (test_and_set_bit(ST_LPM, &fimc->state)) - return 0; - - ret = fimc_lite_stop_capture(fimc, suspend); - if (ret < 0 || !fimc_lite_active(fimc)) - return ret; - - return fimc_pipeline_call(&fimc->ve, close); -} -#endif /* CONFIG_PM_SLEEP */ - -static int fimc_lite_remove(struct platform_device *pdev) -{ - struct fimc_lite *fimc = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; - - if (!pm_runtime_enabled(dev)) - clk_disable_unprepare(fimc->clock); - - pm_runtime_disable(dev); - pm_runtime_set_suspended(dev); - fimc_lite_unregister_capture_subdev(fimc); - vb2_dma_contig_clear_max_seg_size(dev); - fimc_lite_clk_put(fimc); - - dev_info(dev, "Driver unloaded\n"); - return 0; -} - -static const struct dev_pm_ops fimc_lite_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(fimc_lite_suspend, fimc_lite_resume) - SET_RUNTIME_PM_OPS(fimc_lite_runtime_suspend, fimc_lite_runtime_resume, - NULL) -}; - -/* EXYNOS4412 */ -static struct flite_drvdata fimc_lite_drvdata_exynos4 = { - .max_width = 8192, - .max_height = 8192, - .out_width_align = 8, - .win_hor_offs_align = 2, - .out_hor_offs_align = 8, - .max_dma_bufs = 1, - .num_instances = 2, -}; - -/* EXYNOS5250 */ -static struct flite_drvdata fimc_lite_drvdata_exynos5 = { - .max_width = 8192, - .max_height = 8192, - .out_width_align = 8, - .win_hor_offs_align = 2, - .out_hor_offs_align = 8, - .max_dma_bufs = 32, - .num_instances = 3, -}; - -static const struct of_device_id flite_of_match[] = { - { - .compatible = "samsung,exynos4212-fimc-lite", - .data = &fimc_lite_drvdata_exynos4, - }, - { - .compatible = "samsung,exynos5250-fimc-lite", - .data = &fimc_lite_drvdata_exynos5, - }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, flite_of_match); - -static struct platform_driver fimc_lite_driver = { - .probe = fimc_lite_probe, - .remove = fimc_lite_remove, - .driver = { - .of_match_table = flite_of_match, - .name = FIMC_LITE_DRV_NAME, - .pm = &fimc_lite_pm_ops, - } -}; -module_platform_driver(fimc_lite_driver); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" FIMC_LITE_DRV_NAME); diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h deleted file mode 100644 index ddf29e0b5b1c..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-lite.h +++ /dev/null @@ -1,224 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - */ - -#ifndef FIMC_LITE_H_ -#define FIMC_LITE_H_ - -#include <linux/sizes.h> -#include <linux/io.h> -#include <linux/irqreturn.h> -#include <linux/platform_device.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/types.h> -#include <linux/videodev2.h> - -#include <media/media-entity.h> -#include <media/videobuf2-v4l2.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> -#include <media/v4l2-mediabus.h> -#include <media/drv-intf/exynos-fimc.h> - -#define FIMC_LITE_DRV_NAME "exynos-fimc-lite" -#define FLITE_CLK_NAME "flite" -#define FIMC_LITE_MAX_DEVS 3 -#define FLITE_REQ_BUFS_MIN 2 -#define FLITE_DEFAULT_WIDTH 640 -#define FLITE_DEFAULT_HEIGHT 480 - -/* Bit index definitions for struct fimc_lite::state */ -enum { - ST_FLITE_LPM, - ST_FLITE_PENDING, - ST_FLITE_RUN, - ST_FLITE_STREAM, - ST_FLITE_SUSPENDED, - ST_FLITE_OFF, - ST_FLITE_IN_USE, - ST_FLITE_CONFIG, - ST_SENSOR_STREAM, -}; - -#define FLITE_SD_PAD_SINK 0 -#define FLITE_SD_PAD_SOURCE_DMA 1 -#define FLITE_SD_PAD_SOURCE_ISP 2 -#define FLITE_SD_PADS_NUM 3 - -/** - * struct flite_drvdata - FIMC-LITE IP variant data structure - * @max_width: maximum camera interface input width in pixels - * @max_height: maximum camera interface input height in pixels - * @out_width_align: minimum output width alignment in pixels - * @win_hor_offs_align: minimum camera interface crop window horizontal - * offset alignment in pixels - * @out_hor_offs_align: minimum output DMA compose rectangle horizontal - * offset alignment in pixels - * @max_dma_bufs: number of output DMA buffer start address registers - * @num_instances: total number of FIMC-LITE IP instances available - */ -struct flite_drvdata { - unsigned short max_width; - unsigned short max_height; - unsigned short out_width_align; - unsigned short win_hor_offs_align; - unsigned short out_hor_offs_align; - unsigned short max_dma_bufs; - unsigned short num_instances; -}; - -struct fimc_lite_events { - unsigned int data_overflow; -}; - -#define FLITE_MAX_PLANES 1 - -/** - * struct flite_frame - source/target frame properties - * @f_width: full pixel width - * @f_height: full pixel height - * @rect: crop/composition rectangle - * @fmt: pointer to pixel format description data structure - */ -struct flite_frame { - u16 f_width; - u16 f_height; - struct v4l2_rect rect; - const struct fimc_fmt *fmt; -}; - -/** - * struct flite_buffer - video buffer structure - * @vb: vb2 buffer - * @list: list head for the buffers queue - * @addr: DMA buffer start address - * @index: DMA start address register's index - */ -struct flite_buffer { - struct vb2_v4l2_buffer vb; - struct list_head list; - dma_addr_t addr; - unsigned short index; -}; - -/** - * struct fimc_lite - fimc lite structure - * @pdev: pointer to FIMC-LITE platform device - * @dd: SoC specific driver data structure - * @ve: exynos video device entity structure - * @v4l2_dev: pointer to top the level v4l2_device - * @fh: v4l2 file handle - * @subdev: FIMC-LITE subdev - * @vd_pad: media (sink) pad for the capture video node - * @subdev_pads: the subdev media pads - * @sensor: sensor subdev attached to FIMC-LITE directly or through MIPI-CSIS - * @ctrl_handler: v4l2 control handler - * @test_pattern: test pattern controls - * @index: FIMC-LITE platform device index - * @pipeline: video capture pipeline data structure - * @pipeline_ops: media pipeline ops for the video node driver - * @slock: spinlock protecting this data structure and the hw registers - * @lock: mutex serializing video device and the subdev operations - * @clock: FIMC-LITE gate clock - * @regs: memory mapped io registers - * @irq_queue: interrupt handler waitqueue - * @payload: image size in bytes (w x h x bpp) - * @inp_frame: camera input frame structure - * @out_frame: DMA output frame structure - * @out_path: output data path (DMA or FIFO) - * @source_subdev_grp_id: source subdev group id - * @state: driver state flags - * @pending_buf_q: pending buffers queue head - * @active_buf_q: the queue head of buffers scheduled in hardware - * @vb_queue: vb2 buffers queue - * @buf_index: helps to keep track of the DMA start address register index - * @active_buf_count: number of video buffers scheduled in hardware - * @frame_count: the captured frames counter - * @reqbufs_count: the number of buffers requested with REQBUFS ioctl - * @events: event info - * @streaming: is streaming in progress? - */ -struct fimc_lite { - struct platform_device *pdev; - struct flite_drvdata *dd; - struct exynos_video_entity ve; - struct v4l2_device *v4l2_dev; - struct v4l2_fh fh; - struct v4l2_subdev subdev; - struct media_pad vd_pad; - struct media_pad subdev_pads[FLITE_SD_PADS_NUM]; - struct v4l2_subdev *sensor; - struct v4l2_ctrl_handler ctrl_handler; - struct v4l2_ctrl *test_pattern; - int index; - - struct mutex lock; - spinlock_t slock; - - struct clk *clock; - void __iomem *regs; - wait_queue_head_t irq_queue; - - unsigned long payload[FLITE_MAX_PLANES]; - struct flite_frame inp_frame; - struct flite_frame out_frame; - atomic_t out_path; - unsigned int source_subdev_grp_id; - - unsigned long state; - struct list_head pending_buf_q; - struct list_head active_buf_q; - struct vb2_queue vb_queue; - unsigned short buf_index; - unsigned int frame_count; - unsigned int reqbufs_count; - - struct fimc_lite_events events; - bool streaming; -}; - -static inline bool fimc_lite_active(struct fimc_lite *fimc) -{ - unsigned long flags; - bool ret; - - spin_lock_irqsave(&fimc->slock, flags); - ret = fimc->state & (1 << ST_FLITE_RUN) || - fimc->state & (1 << ST_FLITE_PENDING); - spin_unlock_irqrestore(&fimc->slock, flags); - return ret; -} - -static inline void fimc_lite_active_queue_add(struct fimc_lite *dev, - struct flite_buffer *buf) -{ - list_add_tail(&buf->list, &dev->active_buf_q); -} - -static inline struct flite_buffer *fimc_lite_active_queue_pop( - struct fimc_lite *dev) -{ - struct flite_buffer *buf = list_entry(dev->active_buf_q.next, - struct flite_buffer, list); - list_del(&buf->list); - return buf; -} - -static inline void fimc_lite_pending_queue_add(struct fimc_lite *dev, - struct flite_buffer *buf) -{ - list_add_tail(&buf->list, &dev->pending_buf_q); -} - -static inline struct flite_buffer *fimc_lite_pending_queue_pop( - struct fimc_lite *dev) -{ - struct flite_buffer *buf = list_entry(dev->pending_buf_q.next, - struct flite_buffer, list); - list_del(&buf->list); - return buf; -} - -#endif /* FIMC_LITE_H_ */ diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c deleted file mode 100644 index df8e2aa454d8..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ /dev/null @@ -1,773 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Samsung S5P/EXYNOS4 SoC series FIMC (video postprocessor) driver - * - * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#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-v4l2.h> -#include <media/videobuf2-dma-contig.h> - -#include "common.h" -#include "fimc-core.h" -#include "fimc-reg.h" -#include "media-dev.h" - -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; -} - -void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state) -{ - struct vb2_v4l2_buffer *src_vb, *dst_vb; - - if (!ctx || !ctx->fh.m2m_ctx) - return; - - src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - - if (src_vb) - v4l2_m2m_buf_done(src_vb, vb_state); - if (dst_vb) - v4l2_m2m_buf_done(dst_vb, vb_state); - if (src_vb && dst_vb) - v4l2_m2m_job_finish(ctx->fimc_dev->m2m.m2m_dev, - ctx->fh.m2m_ctx); -} - -/* Complete the transaction which has been scheduled for execution. */ -static void fimc_m2m_shutdown(struct fimc_ctx *ctx) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - - if (!fimc_m2m_pending(fimc)) - return; - - fimc_ctx_state_set(FIMC_CTX_SHUT, ctx); - - wait_event_timeout(fimc->irq_queue, - !fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx), - FIMC_SHUTDOWN_TIMEOUT); -} - -static int start_streaming(struct vb2_queue *q, unsigned int count) -{ - struct fimc_ctx *ctx = q->drv_priv; - - return pm_runtime_resume_and_get(&ctx->fimc_dev->pdev->dev); -} - -static void stop_streaming(struct vb2_queue *q) -{ - struct fimc_ctx *ctx = q->drv_priv; - - fimc_m2m_shutdown(ctx); - fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); - pm_runtime_put(&ctx->fimc_dev->pdev->dev); -} - -static void fimc_device_run(void *priv) -{ - struct vb2_v4l2_buffer *src_vb, *dst_vb; - struct fimc_ctx *ctx = priv; - struct fimc_frame *sf, *df; - struct fimc_dev *fimc; - unsigned long flags; - int ret; - - if (WARN(!ctx, "Null context\n")) - return; - - fimc = ctx->fimc_dev; - spin_lock_irqsave(&fimc->slock, flags); - - set_bit(ST_M2M_PEND, &fimc->state); - sf = &ctx->s_frame; - df = &ctx->d_frame; - - if (ctx->state & FIMC_PARAMS) { - /* Prepare the DMA offsets for scaler */ - fimc_prepare_dma_offset(ctx, sf); - fimc_prepare_dma_offset(ctx, df); - } - - src_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - ret = fimc_prepare_addr(ctx, &src_vb->vb2_buf, sf, &sf->addr); - if (ret) - goto dma_unlock; - - dst_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); - ret = fimc_prepare_addr(ctx, &dst_vb->vb2_buf, df, &df->addr); - if (ret) - goto dma_unlock; - - dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; - dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst_vb->flags |= - src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - - /* Reconfigure hardware if the context has changed. */ - if (fimc->m2m.ctx != ctx) { - ctx->state |= FIMC_PARAMS; - fimc->m2m.ctx = ctx; - } - - if (ctx->state & FIMC_PARAMS) { - fimc_set_yuv_order(ctx); - fimc_hw_set_input_path(ctx); - fimc_hw_set_in_dma(ctx); - ret = fimc_set_scaler_info(ctx); - if (ret) - 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); - fimc_hw_set_out_dma(ctx); - if (fimc->drv_data->alpha_color) - fimc_hw_set_rgb_alpha(ctx); - fimc_hw_set_output_path(ctx); - } - fimc_hw_set_input_addr(fimc, &sf->addr); - fimc_hw_set_output_addr(fimc, &df->addr, -1); - - fimc_activate_capture(ctx); - ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP); - fimc_hw_activate_input_dma(fimc, true); - -dma_unlock: - 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, - unsigned int *num_buffers, unsigned int *num_planes, - unsigned int sizes[], struct device *alloc_devs[]) -{ - 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-contiguous 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->payload[i]; - 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 vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); -} - -static const struct vb2_ops fimc_qops = { - .queue_setup = fimc_queue_setup, - .buf_prepare = fimc_buf_prepare, - .buf_queue = fimc_buf_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .stop_streaming = stop_streaming, - .start_streaming = start_streaming, -}; - -/* - * V4L2 ioctl handlers - */ -static int fimc_m2m_querycap(struct file *file, void *fh, - struct v4l2_capability *cap) -{ - struct fimc_dev *fimc = video_drvdata(file); - - __fimc_vidioc_querycap(&fimc->pdev->dev, cap); - return 0; -} - -static int fimc_m2m_enum_fmt(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; - - f->pixelformat = fmt->fourcc; - return 0; -} - -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); - - __fimc_get_format(frame, f); - return 0; -} - -static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - const struct 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; - - 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 void __set_frame_format(struct fimc_frame *frame, struct fimc_fmt *fmt, - struct v4l2_pix_format_mplane *pixm) -{ - int i; - - for (i = 0; i < fmt->memplanes; i++) { - frame->bytesperline[i] = pixm->plane_fmt[i].bytesperline; - frame->payload[i] = pixm->plane_fmt[i].sizeimage; - } - - frame->f_width = pixm->width; - frame->f_height = pixm->height; - frame->o_width = pixm->width; - frame->o_height = pixm->height; - frame->width = pixm->width; - frame->height = pixm->height; - frame->offs_h = 0; - frame->offs_v = 0; - frame->fmt = fmt; -} - -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 fimc_fmt *fmt; - struct vb2_queue *vq; - struct fimc_frame *frame; - int ret; - - ret = fimc_try_fmt_mplane(ctx, f); - if (ret) - return ret; - - vq = v4l2_m2m_get_vq(ctx->fh.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; - - fmt = fimc_find_format(&f->fmt.pix_mp.pixelformat, NULL, - get_m2m_fmt_flags(f->type), 0); - if (!fmt) - return -EINVAL; - - __set_frame_format(frame, fmt, &f->fmt.pix_mp); - - /* Update RGB Alpha control state and value range */ - fimc_alpha_ctrl_update(ctx); - - return 0; -} - -static int fimc_m2m_g_selection(struct file *file, void *fh, - struct v4l2_selection *s) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - struct fimc_frame *frame; - - frame = ctx_get_frame(ctx, s->type); - if (IS_ERR(frame)) - return PTR_ERR(frame); - - switch (s->target) { - case V4L2_SEL_TGT_CROP: - case V4L2_SEL_TGT_CROP_DEFAULT: - case V4L2_SEL_TGT_CROP_BOUNDS: - if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) - return -EINVAL; - break; - case V4L2_SEL_TGT_COMPOSE: - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - break; - default: - return -EINVAL; - } - - switch (s->target) { - case V4L2_SEL_TGT_CROP: - case V4L2_SEL_TGT_COMPOSE: - s->r.left = frame->offs_h; - s->r.top = frame->offs_v; - s->r.width = frame->width; - s->r.height = frame->height; - break; - case V4L2_SEL_TGT_CROP_DEFAULT: - case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - s->r.left = 0; - s->r.top = 0; - s->r.width = frame->o_width; - s->r.height = frame->o_height; - break; - default: - return -EINVAL; - } - return 0; -} - -static int fimc_m2m_try_selection(struct fimc_ctx *ctx, - struct v4l2_selection *s) -{ - struct fimc_dev *fimc = ctx->fimc_dev; - struct fimc_frame *f; - u32 min_size, halign, depth = 0; - int i; - - if (s->r.top < 0 || s->r.left < 0) { - v4l2_err(&fimc->m2m.vfd, - "doesn't support negative values for top & left\n"); - return -EINVAL; - } - if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - f = &ctx->d_frame; - if (s->target != V4L2_SEL_TGT_COMPOSE) - return -EINVAL; - } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - f = &ctx->s_frame; - if (s->target != V4L2_SEL_TGT_CROP) - return -EINVAL; - } 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->memplanes; i++) - depth += f->fmt->depth[i]; - - v4l_bound_align_image(&s->r.width, min_size, f->o_width, - ffs(min_size) - 1, - &s->r.height, min_size, f->o_height, - halign, 64/(ALIGN(depth, 8))); - - /* adjust left/top if cropping rectangle is out of bounds */ - if (s->r.left + s->r.width > f->o_width) - s->r.left = f->o_width - s->r.width; - if (s->r.top + s->r.height > f->o_height) - s->r.top = f->o_height - s->r.height; - - s->r.left = round_down(s->r.left, min_size); - s->r.top = round_down(s->r.top, fimc->variant->hor_offs_align); - - dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d", - s->r.left, s->r.top, s->r.width, s->r.height, - f->f_width, f->f_height); - - return 0; -} - -static int fimc_m2m_s_selection(struct file *file, void *fh, - struct v4l2_selection *s) -{ - 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_selection(ctx, s); - if (ret) - return ret; - - f = (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? - &ctx->s_frame : &ctx->d_frame; - - /* Check to see if scaling ratio is within supported range */ - if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - ret = fimc_check_scaler_ratio(ctx, s->r.width, - s->r.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, s->r.width, - s->r.height, ctx->rotation); - } - if (ret) { - v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n"); - return -EINVAL; - } - - f->offs_h = s->r.left; - f->offs_v = s->r.top; - f->width = s->r.width; - f->height = s->r.height; - - fimc_ctx_state_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 = fimc_m2m_enum_fmt, - .vidioc_enum_fmt_vid_out = fimc_m2m_enum_fmt, - .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 = v4l2_m2m_ioctl_reqbufs, - .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, - .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, - .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, - .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, - .vidioc_streamon = v4l2_m2m_ioctl_streamon, - .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, - .vidioc_g_selection = fimc_m2m_g_selection, - .vidioc_s_selection = fimc_m2m_s_selection, - -}; - -static int queue_init(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq) -{ - struct fimc_ctx *ctx = priv; - int ret; - - src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; - src_vq->drv_priv = ctx; - src_vq->ops = &fimc_qops; - src_vq->mem_ops = &vb2_dma_contig_memops; - src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); - src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - src_vq->lock = &ctx->fimc_dev->lock; - src_vq->dev = &ctx->fimc_dev->pdev->dev; - - ret = vb2_queue_init(src_vq); - if (ret) - return ret; - - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; - dst_vq->drv_priv = ctx; - dst_vq->ops = &fimc_qops; - dst_vq->mem_ops = &vb2_dma_contig_memops; - dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); - dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - dst_vq->lock = &ctx->fimc_dev->lock; - dst_vq->dev = &ctx->fimc_dev->pdev->dev; - - return vb2_queue_init(dst_vq); -} - -static int fimc_m2m_set_default_format(struct fimc_ctx *ctx) -{ - struct v4l2_pix_format_mplane pixm = { - .pixelformat = V4L2_PIX_FMT_RGB32, - .width = 800, - .height = 600, - .plane_fmt[0] = { - .bytesperline = 800 * 4, - .sizeimage = 800 * 4 * 600, - }, - }; - struct fimc_fmt *fmt; - - fmt = fimc_find_format(&pixm.pixelformat, NULL, FMT_FLAGS_M2M, 0); - if (!fmt) - return -EINVAL; - - __set_frame_format(&ctx->s_frame, fmt, &pixm); - __set_frame_format(&ctx->d_frame, fmt, &pixm); - - return 0; -} - -static int fimc_m2m_open(struct file *file) -{ - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_ctx *ctx; - int ret = -EBUSY; - - pr_debug("pid: %d, state: %#lx\n", task_pid_nr(current), fimc->state); - - if (mutex_lock_interruptible(&fimc->lock)) - return -ERESTARTSYS; - /* - * Don't allow simultaneous open() of the mem-to-mem and the - * capture video node that belong to same FIMC IP instance. - */ - if (test_bit(ST_CAPT_BUSY, &fimc->state)) - goto unlock; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) { - ret = -ENOMEM; - goto unlock; - } - v4l2_fh_init(&ctx->fh, &fimc->m2m.vfd); - ctx->fimc_dev = fimc; - - /* Default color format */ - ctx->s_frame.fmt = fimc_get_format(0); - ctx->d_frame.fmt = fimc_get_format(0); - - ret = fimc_ctrls_create(ctx); - if (ret) - goto error_fh; - - /* Use separate control handler per file handle */ - ctx->fh.ctrl_handler = &ctx->ctrls.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_IO_DMA; - ctx->out_path = FIMC_IO_DMA; - ctx->scaler.enabled = 1; - - ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); - if (IS_ERR(ctx->fh.m2m_ctx)) { - ret = PTR_ERR(ctx->fh.m2m_ctx); - goto error_c; - } - - if (fimc->m2m.refcnt++ == 0) - set_bit(ST_M2M_RUN, &fimc->state); - - ret = fimc_m2m_set_default_format(ctx); - if (ret < 0) - goto error_m2m_ctx; - - mutex_unlock(&fimc->lock); - return 0; - -error_m2m_ctx: - v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); -error_c: - fimc_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); -error_fh: - v4l2_fh_exit(&ctx->fh); - kfree(ctx); -unlock: - mutex_unlock(&fimc->lock); - 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); - - mutex_lock(&fimc->lock); - - v4l2_m2m_ctx_release(ctx->fh.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); - - mutex_unlock(&fimc->lock); - return 0; -} - -static const struct v4l2_file_operations fimc_m2m_fops = { - .owner = THIS_MODULE, - .open = fimc_m2m_open, - .release = fimc_m2m_release, - .poll = v4l2_m2m_fop_poll, - .unlocked_ioctl = video_ioctl2, - .mmap = v4l2_m2m_fop_mmap, -}; - -static const struct v4l2_m2m_ops m2m_ops = { - .device_run = fimc_device_run, - .job_abort = fimc_job_abort, -}; - -int fimc_register_m2m_device(struct fimc_dev *fimc, - struct v4l2_device *v4l2_dev) -{ - struct video_device *vfd = &fimc->m2m.vfd; - int ret; - - fimc->v4l2_dev = v4l2_dev; - - memset(vfd, 0, sizeof(*vfd)); - 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_empty; - vfd->lock = &fimc->lock; - vfd->vfl_dir = VFL_DIR_M2M; - vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE; - set_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags); - - snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id); - video_set_drvdata(vfd, fimc); - - 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"); - return PTR_ERR(fimc->m2m.m2m_dev); - } - - ret = media_entity_pads_init(&vfd->entity, 0, NULL); - if (ret) - goto err_me; - - ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); - if (ret) - goto err_vd; - - v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n", - vfd->name, video_device_node_name(vfd)); - return 0; - -err_vd: - media_entity_cleanup(&vfd->entity); -err_me: - v4l2_m2m_release(fimc->m2m.m2m_dev); - 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 (video_is_registered(&fimc->m2m.vfd)) { - video_unregister_device(&fimc->m2m.vfd); - media_entity_cleanup(&fimc->m2m.vfd.entity); - } -} diff --git a/drivers/media/platform/exynos4-is/fimc-reg.c b/drivers/media/platform/exynos4-is/fimc-reg.c deleted file mode 100644 index 95165a2cc7d1..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-reg.c +++ /dev/null @@ -1,846 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Register interface file for Samsung Camera Interface (FIMC) driver - * - * Copyright (C) 2010 - 2013 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki <s.nawrocki@samsung.com> -*/ - -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/regmap.h> - -#include <media/drv-intf/exynos-fimc.h> -#include "media-dev.h" - -#include "fimc-reg.h" -#include "fimc-core.h" - -void fimc_hw_reset(struct fimc_dev *dev) -{ - u32 cfg; - - cfg = readl(dev->regs + FIMC_REG_CISRCFMT); - cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; - writel(cfg, dev->regs + FIMC_REG_CISRCFMT); - - /* Software reset. */ - cfg = readl(dev->regs + FIMC_REG_CIGCTRL); - cfg |= (FIMC_REG_CIGCTRL_SWRST | FIMC_REG_CIGCTRL_IRQ_LEVEL); - writel(cfg, dev->regs + FIMC_REG_CIGCTRL); - udelay(10); - - cfg = readl(dev->regs + FIMC_REG_CIGCTRL); - cfg &= ~FIMC_REG_CIGCTRL_SWRST; - writel(cfg, dev->regs + FIMC_REG_CIGCTRL); - - if (dev->drv_data->out_buf_count > 4) - fimc_hw_set_dma_seq(dev, 0xF); -} - -static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx) -{ - u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL; - - if (ctx->hflip) - flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR; - if (ctx->vflip) - flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR; - - if (ctx->rotation <= 90) - return flip; - - return (flip ^ FIMC_REG_MSCTRL_FLIP_180) & FIMC_REG_MSCTRL_FLIP_180; -} - -static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx) -{ - u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL; - - if (ctx->hflip) - flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR; - if (ctx->vflip) - flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR; - - if (ctx->rotation <= 90) - return flip; - - return (flip ^ FIMC_REG_CITRGFMT_FLIP_180) & FIMC_REG_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 + FIMC_REG_CITRGFMT); - cfg &= ~(FIMC_REG_CITRGFMT_INROT90 | FIMC_REG_CITRGFMT_OUTROT90 | - FIMC_REG_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_IO_LCDFIFO) - cfg |= FIMC_REG_CITRGFMT_INROT90; - else - cfg |= FIMC_REG_CITRGFMT_OUTROT90; - } - - if (ctx->out_path == FIMC_IO_DMA) { - cfg |= fimc_hw_get_target_flip(ctx); - writel(cfg, dev->regs + FIMC_REG_CITRGFMT); - } else { - /* LCD FIFO path */ - flip = readl(dev->regs + FIMC_REG_MSCTRL); - flip &= ~FIMC_REG_MSCTRL_FLIP_MASK; - flip |= fimc_hw_get_in_flip(ctx); - writel(flip, dev->regs + FIMC_REG_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 + FIMC_REG_CITRGFMT); - cfg &= ~(FIMC_REG_CITRGFMT_FMT_MASK | FIMC_REG_CITRGFMT_HSIZE_MASK | - FIMC_REG_CITRGFMT_VSIZE_MASK); - - switch (frame->fmt->color) { - case FIMC_FMT_RGB444...FIMC_FMT_RGB888: - cfg |= FIMC_REG_CITRGFMT_RGB; - break; - case FIMC_FMT_YCBCR420: - cfg |= FIMC_REG_CITRGFMT_YCBCR420; - break; - case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422: - if (frame->fmt->colplanes == 1) - cfg |= FIMC_REG_CITRGFMT_YCBCR422_1P; - else - cfg |= FIMC_REG_CITRGFMT_YCBCR422; - break; - default: - break; - } - - if (ctx->rotation == 90 || ctx->rotation == 270) - cfg |= (frame->height << 16) | frame->width; - else - cfg |= (frame->width << 16) | frame->height; - - writel(cfg, dev->regs + FIMC_REG_CITRGFMT); - - cfg = readl(dev->regs + FIMC_REG_CITAREA); - cfg &= ~FIMC_REG_CITAREA_MASK; - cfg |= (frame->width * frame->height); - writel(cfg, dev->regs + FIMC_REG_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 = (frame->f_height << 16) | frame->f_width; - writel(cfg, dev->regs + FIMC_REG_ORGOSIZE); - - /* Select color space conversion equation (HD/SD size).*/ - cfg = readl(dev->regs + FIMC_REG_CIGCTRL); - if (frame->f_width >= 1280) /* HD */ - cfg |= FIMC_REG_CIGCTRL_CSC_ITU601_709; - else /* SD */ - cfg &= ~FIMC_REG_CIGCTRL_CSC_ITU601_709; - writel(cfg, dev->regs + FIMC_REG_CIGCTRL); - -} - -void fimc_hw_set_out_dma(struct fimc_ctx *ctx) -{ - 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; - u32 cfg; - - /* Set the input dma offsets. */ - cfg = (offset->y_v << 16) | offset->y_h; - writel(cfg, dev->regs + FIMC_REG_CIOYOFF); - - cfg = (offset->cb_v << 16) | offset->cb_h; - writel(cfg, dev->regs + FIMC_REG_CIOCBOFF); - - cfg = (offset->cr_v << 16) | offset->cr_h; - writel(cfg, dev->regs + FIMC_REG_CIOCROFF); - - fimc_hw_set_out_dma_size(ctx); - - /* Configure chroma components order. */ - cfg = readl(dev->regs + FIMC_REG_CIOCTRL); - - cfg &= ~(FIMC_REG_CIOCTRL_ORDER2P_MASK | - FIMC_REG_CIOCTRL_ORDER422_MASK | - FIMC_REG_CIOCTRL_YCBCR_PLANE_MASK | - FIMC_REG_CIOCTRL_RGB16FMT_MASK); - - if (fmt->colplanes == 1) - cfg |= ctx->out_order_1p; - else if (fmt->colplanes == 2) - cfg |= ctx->out_order_2p | FIMC_REG_CIOCTRL_YCBCR_2PLANE; - else if (fmt->colplanes == 3) - cfg |= FIMC_REG_CIOCTRL_YCBCR_3PLANE; - - if (fmt->color == FIMC_FMT_RGB565) - cfg |= FIMC_REG_CIOCTRL_RGB565; - else if (fmt->color == FIMC_FMT_RGB555) - cfg |= FIMC_REG_CIOCTRL_ARGB1555; - else if (fmt->color == FIMC_FMT_RGB444) - cfg |= FIMC_REG_CIOCTRL_ARGB4444; - - writel(cfg, dev->regs + FIMC_REG_CIOCTRL); -} - -static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable) -{ - u32 cfg = readl(dev->regs + FIMC_REG_ORGISIZE); - if (enable) - cfg |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN; - else - cfg &= ~FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN; - writel(cfg, dev->regs + FIMC_REG_ORGISIZE); -} - -void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable) -{ - u32 cfg = readl(dev->regs + FIMC_REG_CIOCTRL); - if (enable) - cfg |= FIMC_REG_CIOCTRL_LASTIRQ_ENABLE; - else - cfg &= ~FIMC_REG_CIOCTRL_LASTIRQ_ENABLE; - writel(cfg, dev->regs + FIMC_REG_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 = shfactor << 28; - - cfg |= (sc->pre_hratio << 16) | sc->pre_vratio; - writel(cfg, dev->regs + FIMC_REG_CISCPRERATIO); - - cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height; - writel(cfg, dev->regs + FIMC_REG_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 + FIMC_REG_CISCCTRL); - - cfg &= ~(FIMC_REG_CISCCTRL_CSCR2Y_WIDE | FIMC_REG_CISCCTRL_CSCY2R_WIDE | - FIMC_REG_CISCCTRL_SCALEUP_H | FIMC_REG_CISCCTRL_SCALEUP_V | - FIMC_REG_CISCCTRL_SCALERBYPASS | FIMC_REG_CISCCTRL_ONE2ONE | - FIMC_REG_CISCCTRL_INRGB_FMT_MASK | FIMC_REG_CISCCTRL_OUTRGB_FMT_MASK | - FIMC_REG_CISCCTRL_INTERLACE | FIMC_REG_CISCCTRL_RGB_EXT); - - if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW)) - cfg |= (FIMC_REG_CISCCTRL_CSCR2Y_WIDE | - FIMC_REG_CISCCTRL_CSCY2R_WIDE); - - if (!sc->enabled) - cfg |= FIMC_REG_CISCCTRL_SCALERBYPASS; - - if (sc->scaleup_h) - cfg |= FIMC_REG_CISCCTRL_SCALEUP_H; - - if (sc->scaleup_v) - cfg |= FIMC_REG_CISCCTRL_SCALEUP_V; - - if (sc->copy_mode) - cfg |= FIMC_REG_CISCCTRL_ONE2ONE; - - if (ctx->in_path == FIMC_IO_DMA) { - switch (src_frame->fmt->color) { - case FIMC_FMT_RGB565: - cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB565; - break; - case FIMC_FMT_RGB666: - cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB666; - break; - case FIMC_FMT_RGB888: - cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB888; - break; - } - } - - if (ctx->out_path == FIMC_IO_DMA) { - u32 color = dst_frame->fmt->color; - - if (color >= FIMC_FMT_RGB444 && color <= FIMC_FMT_RGB565) - cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565; - else if (color == FIMC_FMT_RGB666) - cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666; - else if (color == FIMC_FMT_RGB888) - cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888; - } else { - cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888; - - if (ctx->flags & FIMC_SCAN_MODE_INTERLACED) - cfg |= FIMC_REG_CISCCTRL_INTERLACE; - } - - writel(cfg, dev->regs + FIMC_REG_CISCCTRL); -} - -void fimc_hw_set_mainscaler(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - const struct 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 + FIMC_REG_CISCCTRL); - cfg &= ~(FIMC_REG_CISCCTRL_MHRATIO_MASK | - FIMC_REG_CISCCTRL_MVRATIO_MASK); - - if (variant->has_mainscaler_ext) { - cfg |= FIMC_REG_CISCCTRL_MHRATIO_EXT(sc->main_hratio); - cfg |= FIMC_REG_CISCCTRL_MVRATIO_EXT(sc->main_vratio); - writel(cfg, dev->regs + FIMC_REG_CISCCTRL); - - cfg = readl(dev->regs + FIMC_REG_CIEXTEN); - - cfg &= ~(FIMC_REG_CIEXTEN_MVRATIO_EXT_MASK | - FIMC_REG_CIEXTEN_MHRATIO_EXT_MASK); - cfg |= FIMC_REG_CIEXTEN_MHRATIO_EXT(sc->main_hratio); - cfg |= FIMC_REG_CIEXTEN_MVRATIO_EXT(sc->main_vratio); - writel(cfg, dev->regs + FIMC_REG_CIEXTEN); - } else { - cfg |= FIMC_REG_CISCCTRL_MHRATIO(sc->main_hratio); - cfg |= FIMC_REG_CISCCTRL_MVRATIO(sc->main_vratio); - writel(cfg, dev->regs + FIMC_REG_CISCCTRL); - } -} - -void fimc_hw_enable_capture(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - u32 cfg; - - cfg = readl(dev->regs + FIMC_REG_CIIMGCPT); - cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE; - - if (ctx->scaler.enabled) - cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC; - else - cfg &= FIMC_REG_CIIMGCPT_IMGCPTEN_SC; - - cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN; - writel(cfg, dev->regs + FIMC_REG_CIIMGCPT); -} - -void fimc_hw_disable_capture(struct fimc_dev *dev) -{ - u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT); - cfg &= ~(FIMC_REG_CIIMGCPT_IMGCPTEN | - FIMC_REG_CIIMGCPT_IMGCPTEN_SC); - writel(cfg, dev->regs + FIMC_REG_CIIMGCPT); -} - -void fimc_hw_set_effect(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - struct fimc_effect *effect = &ctx->effect; - u32 cfg = 0; - - if (effect->type != FIMC_REG_CIIMGEFF_FIN_BYPASS) { - cfg |= FIMC_REG_CIIMGEFF_IE_SC_AFTER | - FIMC_REG_CIIMGEFF_IE_ENABLE; - cfg |= effect->type; - if (effect->type == FIMC_REG_CIIMGEFF_FIN_ARBITRARY) - cfg |= (effect->pat_cb << 13) | effect->pat_cr; - } - - writel(cfg, dev->regs + FIMC_REG_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 + FIMC_REG_CIOCTRL); - cfg &= ~FIMC_REG_CIOCTRL_ALPHA_OUT_MASK; - cfg |= (frame->alpha << 4); - writel(cfg, dev->regs + FIMC_REG_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_IO_LCDFIFO == ctx->out_path) - cfg_r |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN; - - cfg_o |= (frame->f_height << 16) | frame->f_width; - cfg_r |= (frame->height << 16) | frame->width; - - writel(cfg_o, dev->regs + FIMC_REG_ORGISIZE); - writel(cfg_r, dev->regs + FIMC_REG_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 = (offset->y_v << 16) | offset->y_h; - writel(cfg, dev->regs + FIMC_REG_CIIYOFF); - - cfg = (offset->cb_v << 16) | offset->cb_h; - writel(cfg, dev->regs + FIMC_REG_CIICBOFF); - - cfg = (offset->cr_v << 16) | offset->cr_h; - writel(cfg, dev->regs + FIMC_REG_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_IO_LCDFIFO); - - /* Set the input DMA to process single frame only. */ - cfg = readl(dev->regs + FIMC_REG_MSCTRL); - cfg &= ~(FIMC_REG_MSCTRL_INFORMAT_MASK - | FIMC_REG_MSCTRL_IN_BURST_COUNT_MASK - | FIMC_REG_MSCTRL_INPUT_MASK - | FIMC_REG_MSCTRL_C_INT_IN_MASK - | FIMC_REG_MSCTRL_2P_IN_ORDER_MASK - | FIMC_REG_MSCTRL_ORDER422_MASK); - - cfg |= (FIMC_REG_MSCTRL_IN_BURST_COUNT(4) - | FIMC_REG_MSCTRL_INPUT_MEMORY - | FIMC_REG_MSCTRL_FIFO_CTRL_FULL); - - switch (frame->fmt->color) { - case FIMC_FMT_RGB565...FIMC_FMT_RGB888: - cfg |= FIMC_REG_MSCTRL_INFORMAT_RGB; - break; - case FIMC_FMT_YCBCR420: - cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR420; - - if (frame->fmt->colplanes == 2) - cfg |= ctx->in_order_2p | FIMC_REG_MSCTRL_C_INT_IN_2PLANE; - else - cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE; - - break; - case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422: - if (frame->fmt->colplanes == 1) { - cfg |= ctx->in_order_1p - | FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P; - } else { - cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR422; - - if (frame->fmt->colplanes == 2) - cfg |= ctx->in_order_2p - | FIMC_REG_MSCTRL_C_INT_IN_2PLANE; - else - cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE; - } - break; - default: - break; - } - - writel(cfg, dev->regs + FIMC_REG_MSCTRL); - - /* Input/output DMA linear/tiled mode. */ - cfg = readl(dev->regs + FIMC_REG_CIDMAPARAM); - cfg &= ~FIMC_REG_CIDMAPARAM_TILE_MASK; - - if (tiled_fmt(ctx->s_frame.fmt)) - cfg |= FIMC_REG_CIDMAPARAM_R_64X32; - - if (tiled_fmt(ctx->d_frame.fmt)) - cfg |= FIMC_REG_CIDMAPARAM_W_64X32; - - writel(cfg, dev->regs + FIMC_REG_CIDMAPARAM); -} - - -void fimc_hw_set_input_path(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - - u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL); - cfg &= ~FIMC_REG_MSCTRL_INPUT_MASK; - - if (ctx->in_path == FIMC_IO_DMA) - cfg |= FIMC_REG_MSCTRL_INPUT_MEMORY; - else - cfg |= FIMC_REG_MSCTRL_INPUT_EXTCAM; - - writel(cfg, dev->regs + FIMC_REG_MSCTRL); -} - -void fimc_hw_set_output_path(struct fimc_ctx *ctx) -{ - struct fimc_dev *dev = ctx->fimc_dev; - - u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL); - cfg &= ~FIMC_REG_CISCCTRL_LCDPATHEN_FIFO; - if (ctx->out_path == FIMC_IO_LCDFIFO) - cfg |= FIMC_REG_CISCCTRL_LCDPATHEN_FIFO; - writel(cfg, dev->regs + FIMC_REG_CISCCTRL); -} - -void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *addr) -{ - u32 cfg = readl(dev->regs + FIMC_REG_CIREAL_ISIZE); - cfg |= FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS; - writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE); - - writel(addr->y, dev->regs + FIMC_REG_CIIYSA(0)); - writel(addr->cb, dev->regs + FIMC_REG_CIICBSA(0)); - writel(addr->cr, dev->regs + FIMC_REG_CIICRSA(0)); - - cfg &= ~FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS; - writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE); -} - -void fimc_hw_set_output_addr(struct fimc_dev *dev, - struct fimc_addr *addr, int index) -{ - int i = (index == -1) ? 0 : index; - do { - writel(addr->y, dev->regs + FIMC_REG_CIOYSA(i)); - writel(addr->cb, dev->regs + FIMC_REG_CIOCBSA(i)); - writel(addr->cr, dev->regs + FIMC_REG_CIOCRSA(i)); - dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X", - i, addr->y, addr->cb, addr->cr); - } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS); -} - -int fimc_hw_set_camera_polarity(struct fimc_dev *fimc, - struct fimc_source_info *cam) -{ - u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL); - - cfg &= ~(FIMC_REG_CIGCTRL_INVPOLPCLK | FIMC_REG_CIGCTRL_INVPOLVSYNC | - FIMC_REG_CIGCTRL_INVPOLHREF | FIMC_REG_CIGCTRL_INVPOLHSYNC | - FIMC_REG_CIGCTRL_INVPOLFIELD); - - if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) - cfg |= FIMC_REG_CIGCTRL_INVPOLPCLK; - - if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) - cfg |= FIMC_REG_CIGCTRL_INVPOLVSYNC; - - if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) - cfg |= FIMC_REG_CIGCTRL_INVPOLHREF; - - if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) - cfg |= FIMC_REG_CIGCTRL_INVPOLHSYNC; - - if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW) - cfg |= FIMC_REG_CIGCTRL_INVPOLFIELD; - - writel(cfg, fimc->regs + FIMC_REG_CIGCTRL); - - return 0; -} - -struct mbus_pixfmt_desc { - u32 pixelcode; - u32 cisrcfmt; - u16 bus_width; -}; - -static const struct mbus_pixfmt_desc pix_desc[] = { - { MEDIA_BUS_FMT_YUYV8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCBYCR, 8 }, - { MEDIA_BUS_FMT_YVYU8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCRYCB, 8 }, - { MEDIA_BUS_FMT_VYUY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CRYCBY, 8 }, - { MEDIA_BUS_FMT_UYVY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CBYCRY, 8 }, -}; - -int fimc_hw_set_camera_source(struct fimc_dev *fimc, - struct fimc_source_info *source) -{ - struct fimc_vid_cap *vc = &fimc->vid_cap; - struct fimc_frame *f = &vc->ctx->s_frame; - u32 bus_width, cfg = 0; - int i; - - switch (source->fimc_bus_type) { - case FIMC_BUS_TYPE_ITU_601: - case FIMC_BUS_TYPE_ITU_656: - if (fimc_fmt_is_user_defined(f->fmt->color)) { - cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; - break; - } - - for (i = 0; i < ARRAY_SIZE(pix_desc); i++) { - if (vc->ci_fmt.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(&vc->ve.vdev, - "Camera color format not supported: %d\n", - vc->ci_fmt.code); - return -EINVAL; - } - - if (source->fimc_bus_type == FIMC_BUS_TYPE_ITU_601) { - if (bus_width == 8) - cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; - else if (bus_width == 16) - cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT; - } /* else defaults to ITU-R BT.656 8-bit */ - break; - case FIMC_BUS_TYPE_MIPI_CSI2: - if (fimc_fmt_is_user_defined(f->fmt->color)) - cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; - break; - default: - case FIMC_BUS_TYPE_ISP_WRITEBACK: - /* Anything to do here ? */ - break; - } - - cfg |= (f->o_width << 16) | f->o_height; - writel(cfg, fimc->regs + FIMC_REG_CISRCFMT); - return 0; -} - -void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f) -{ - u32 hoff2, voff2; - - u32 cfg = readl(fimc->regs + FIMC_REG_CIWDOFST); - - cfg &= ~(FIMC_REG_CIWDOFST_HOROFF_MASK | FIMC_REG_CIWDOFST_VEROFF_MASK); - cfg |= FIMC_REG_CIWDOFST_OFF_EN | - (f->offs_h << 16) | f->offs_v; - - writel(cfg, fimc->regs + FIMC_REG_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 = (hoff2 << 16) | voff2; - writel(cfg, fimc->regs + FIMC_REG_CIWDOFST2); -} - -int fimc_hw_set_camera_type(struct fimc_dev *fimc, - struct fimc_source_info *source) -{ - struct fimc_vid_cap *vid_cap = &fimc->vid_cap; - u32 csis_data_alignment = 32; - u32 cfg, tmp; - - cfg = readl(fimc->regs + FIMC_REG_CIGCTRL); - - /* Select ITU B interface, disable Writeback path and test pattern. */ - cfg &= ~(FIMC_REG_CIGCTRL_TESTPAT_MASK | FIMC_REG_CIGCTRL_SELCAM_ITU_A | - FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB | - FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG | - FIMC_REG_CIGCTRL_SELWB_A); - - switch (source->fimc_bus_type) { - case FIMC_BUS_TYPE_MIPI_CSI2: - cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI; - - if (source->mux_id == 0) - cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A; - - /* TODO: add remaining supported formats. */ - switch (vid_cap->ci_fmt.code) { - case MEDIA_BUS_FMT_VYUY8_2X8: - tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT; - break; - case MEDIA_BUS_FMT_JPEG_1X8: - case MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8: - tmp = FIMC_REG_CSIIMGFMT_USER(1); - cfg |= FIMC_REG_CIGCTRL_CAM_JPEG; - break; - default: - v4l2_err(&vid_cap->ve.vdev, - "Not supported camera pixel format: %#x\n", - vid_cap->ci_fmt.code); - return -EINVAL; - } - tmp |= (csis_data_alignment == 32) << 8; - - writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT); - break; - case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656: - if (source->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */ - cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A; - if (vid_cap->ci_fmt.code == MEDIA_BUS_FMT_JPEG_1X8) - cfg |= FIMC_REG_CIGCTRL_CAM_JPEG; - break; - case FIMC_BUS_TYPE_LCD_WRITEBACK_A: - cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB; - fallthrough; - case FIMC_BUS_TYPE_ISP_WRITEBACK: - if (fimc->variant->has_isp_wb) - cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB; - else - WARN_ONCE(1, "ISP Writeback input is not supported\n"); - break; - default: - v4l2_err(&vid_cap->ve.vdev, - "Invalid FIMC bus type selected: %d\n", - source->fimc_bus_type); - return -EINVAL; - } - writel(cfg, fimc->regs + FIMC_REG_CIGCTRL); - - return 0; -} - -void fimc_hw_clear_irq(struct fimc_dev *dev) -{ - u32 cfg = readl(dev->regs + FIMC_REG_CIGCTRL); - cfg |= FIMC_REG_CIGCTRL_IRQ_CLR; - writel(cfg, dev->regs + FIMC_REG_CIGCTRL); -} - -void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on) -{ - u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL); - if (on) - cfg |= FIMC_REG_CISCCTRL_SCALERSTART; - else - cfg &= ~FIMC_REG_CISCCTRL_SCALERSTART; - writel(cfg, dev->regs + FIMC_REG_CISCCTRL); -} - -void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on) -{ - u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL); - if (on) - cfg |= FIMC_REG_MSCTRL_ENVID; - else - cfg &= ~FIMC_REG_MSCTRL_ENVID; - writel(cfg, dev->regs + FIMC_REG_MSCTRL); -} - -/* Return an index to the buffer actually being written. */ -s32 fimc_hw_get_frame_index(struct fimc_dev *dev) -{ - s32 reg; - - if (dev->drv_data->cistatus2) { - reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f; - return reg - 1; - } - - reg = readl(dev->regs + FIMC_REG_CISTATUS); - - return (reg & FIMC_REG_CISTATUS_FRAMECNT_MASK) >> - FIMC_REG_CISTATUS_FRAMECNT_SHIFT; -} - -/* Return an index to the buffer being written previously. */ -s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev) -{ - s32 reg; - - if (!dev->drv_data->cistatus2) - return -1; - - reg = readl(dev->regs + FIMC_REG_CISTATUS2); - return ((reg >> 7) & 0x3f) - 1; -} - -/* Locking: the caller holds fimc->slock */ -void fimc_activate_capture(struct fimc_ctx *ctx) -{ - fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled); - fimc_hw_enable_capture(ctx); -} - -void fimc_deactivate_capture(struct fimc_dev *fimc) -{ - fimc_hw_en_lastirq(fimc, true); - fimc_hw_disable_capture(fimc); - fimc_hw_enable_scaler(fimc, false); - fimc_hw_en_lastirq(fimc, false); -} - -int fimc_hw_camblk_cfg_writeback(struct fimc_dev *fimc) -{ - struct regmap *map = fimc->sysreg; - unsigned int mask, val, camblk_cfg; - int ret; - - if (map == NULL) - return 0; - - ret = regmap_read(map, SYSREG_CAMBLK, &camblk_cfg); - if (ret < 0 || ((camblk_cfg & 0x00700000) >> 20 != 0x3)) - return ret; - - if (!WARN(fimc->id >= 3, "not supported id: %d\n", fimc->id)) - val = 0x1 << (fimc->id + 20); - else - val = 0; - - mask = SYSREG_CAMBLK_FIFORST_ISP | SYSREG_CAMBLK_ISPWB_FULL_EN; - ret = regmap_update_bits(map, SYSREG_CAMBLK, mask, val); - if (ret < 0) - return ret; - - usleep_range(1000, 2000); - - val |= SYSREG_CAMBLK_FIFORST_ISP; - ret = regmap_update_bits(map, SYSREG_CAMBLK, mask, val); - if (ret < 0) - return ret; - - mask = SYSREG_ISPBLK_FIFORST_CAM_BLK; - ret = regmap_update_bits(map, SYSREG_ISPBLK, mask, ~mask); - if (ret < 0) - return ret; - - usleep_range(1000, 2000); - - return regmap_update_bits(map, SYSREG_ISPBLK, mask, mask); -} diff --git a/drivers/media/platform/exynos4-is/fimc-reg.h b/drivers/media/platform/exynos4-is/fimc-reg.h deleted file mode 100644 index b9b33aa1f12f..000000000000 --- a/drivers/media/platform/exynos4-is/fimc-reg.h +++ /dev/null @@ -1,338 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung camera host interface (FIMC) registers definition - * - * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd. - */ - -#ifndef FIMC_REG_H_ -#define FIMC_REG_H_ - -#include <linux/bitops.h> - -#include "fimc-core.h" - -/* Input source format */ -#define FIMC_REG_CISRCFMT 0x00 -#define FIMC_REG_CISRCFMT_ITU601_8BIT BIT(31) -#define FIMC_REG_CISRCFMT_ITU601_16BIT BIT(29) -#define FIMC_REG_CISRCFMT_ORDER422_YCBYCR (0 << 14) -#define FIMC_REG_CISRCFMT_ORDER422_YCRYCB (1 << 14) -#define FIMC_REG_CISRCFMT_ORDER422_CBYCRY (2 << 14) -#define FIMC_REG_CISRCFMT_ORDER422_CRYCBY (3 << 14) - -/* Window offset */ -#define FIMC_REG_CIWDOFST 0x04 -#define FIMC_REG_CIWDOFST_OFF_EN BIT(31) -#define FIMC_REG_CIWDOFST_CLROVFIY BIT(30) -#define FIMC_REG_CIWDOFST_CLROVRLB BIT(29) -#define FIMC_REG_CIWDOFST_HOROFF_MASK (0x7ff << 16) -#define FIMC_REG_CIWDOFST_CLROVFICB BIT(15) -#define FIMC_REG_CIWDOFST_CLROVFICR BIT(14) -#define FIMC_REG_CIWDOFST_VEROFF_MASK (0xfff << 0) - -/* Global control */ -#define FIMC_REG_CIGCTRL 0x08 -#define FIMC_REG_CIGCTRL_SWRST BIT(31) -#define FIMC_REG_CIGCTRL_CAMRST_A BIT(30) -#define FIMC_REG_CIGCTRL_SELCAM_ITU_A BIT(29) -#define FIMC_REG_CIGCTRL_TESTPAT_NORMAL (0 << 27) -#define FIMC_REG_CIGCTRL_TESTPAT_COLOR_BAR (1 << 27) -#define FIMC_REG_CIGCTRL_TESTPAT_HOR_INC (2 << 27) -#define FIMC_REG_CIGCTRL_TESTPAT_VER_INC (3 << 27) -#define FIMC_REG_CIGCTRL_TESTPAT_MASK (3 << 27) -#define FIMC_REG_CIGCTRL_TESTPAT_SHIFT 27 -#define FIMC_REG_CIGCTRL_INVPOLPCLK BIT(26) -#define FIMC_REG_CIGCTRL_INVPOLVSYNC BIT(25) -#define FIMC_REG_CIGCTRL_INVPOLHREF BIT(24) -#define FIMC_REG_CIGCTRL_IRQ_OVFEN BIT(22) -#define FIMC_REG_CIGCTRL_HREF_MASK BIT(21) -#define FIMC_REG_CIGCTRL_IRQ_LEVEL BIT(20) -#define FIMC_REG_CIGCTRL_IRQ_CLR BIT(19) -#define FIMC_REG_CIGCTRL_IRQ_ENABLE BIT(16) -#define FIMC_REG_CIGCTRL_SHDW_DISABLE BIT(12) -/* 0 - selects Writeback A (LCD), 1 - selects Writeback B (LCD/ISP) */ -#define FIMC_REG_CIGCTRL_SELWB_A BIT(10) -#define FIMC_REG_CIGCTRL_CAM_JPEG BIT(8) -#define FIMC_REG_CIGCTRL_SELCAM_MIPI_A BIT(7) -#define FIMC_REG_CIGCTRL_CAMIF_SELWB BIT(6) -/* 0 - ITU601; 1 - ITU709 */ -#define FIMC_REG_CIGCTRL_CSC_ITU601_709 BIT(5) -#define FIMC_REG_CIGCTRL_INVPOLHSYNC BIT(4) -#define FIMC_REG_CIGCTRL_SELCAM_MIPI BIT(3) -#define FIMC_REG_CIGCTRL_INVPOLFIELD BIT(1) -#define FIMC_REG_CIGCTRL_INTERLACE BIT(0) - -/* Window offset 2 */ -#define FIMC_REG_CIWDOFST2 0x14 -#define FIMC_REG_CIWDOFST2_HOROFF_MASK (0xfff << 16) -#define FIMC_REG_CIWDOFST2_VEROFF_MASK (0xfff << 0) - -/* Output DMA Y/Cb/Cr plane start addresses */ -#define FIMC_REG_CIOYSA(n) (0x18 + (n) * 4) -#define FIMC_REG_CIOCBSA(n) (0x28 + (n) * 4) -#define FIMC_REG_CIOCRSA(n) (0x38 + (n) * 4) - -/* Target image format */ -#define FIMC_REG_CITRGFMT 0x48 -#define FIMC_REG_CITRGFMT_INROT90 BIT(31) -#define FIMC_REG_CITRGFMT_YCBCR420 (0 << 29) -#define FIMC_REG_CITRGFMT_YCBCR422 (1 << 29) -#define FIMC_REG_CITRGFMT_YCBCR422_1P (2 << 29) -#define FIMC_REG_CITRGFMT_RGB (3 << 29) -#define FIMC_REG_CITRGFMT_FMT_MASK (3 << 29) -#define FIMC_REG_CITRGFMT_HSIZE_MASK (0xfff << 16) -#define FIMC_REG_CITRGFMT_FLIP_SHIFT 14 -#define FIMC_REG_CITRGFMT_FLIP_NORMAL (0 << 14) -#define FIMC_REG_CITRGFMT_FLIP_X_MIRROR (1 << 14) -#define FIMC_REG_CITRGFMT_FLIP_Y_MIRROR (2 << 14) -#define FIMC_REG_CITRGFMT_FLIP_180 (3 << 14) -#define FIMC_REG_CITRGFMT_FLIP_MASK (3 << 14) -#define FIMC_REG_CITRGFMT_OUTROT90 BIT(13) -#define FIMC_REG_CITRGFMT_VSIZE_MASK (0xfff << 0) - -/* Output DMA control */ -#define FIMC_REG_CIOCTRL 0x4c -#define FIMC_REG_CIOCTRL_ORDER422_MASK (3 << 0) -#define FIMC_REG_CIOCTRL_ORDER422_YCBYCR (0 << 0) -#define FIMC_REG_CIOCTRL_ORDER422_YCRYCB (1 << 0) -#define FIMC_REG_CIOCTRL_ORDER422_CBYCRY (2 << 0) -#define FIMC_REG_CIOCTRL_ORDER422_CRYCBY (3 << 0) -#define FIMC_REG_CIOCTRL_LASTIRQ_ENABLE BIT(2) -#define FIMC_REG_CIOCTRL_YCBCR_3PLANE (0 << 3) -#define FIMC_REG_CIOCTRL_YCBCR_2PLANE (1 << 3) -#define FIMC_REG_CIOCTRL_YCBCR_PLANE_MASK (1 << 3) -#define FIMC_REG_CIOCTRL_ALPHA_OUT_MASK (0xff << 4) -#define FIMC_REG_CIOCTRL_RGB16FMT_MASK (3 << 16) -#define FIMC_REG_CIOCTRL_RGB565 (0 << 16) -#define FIMC_REG_CIOCTRL_ARGB1555 (1 << 16) -#define FIMC_REG_CIOCTRL_ARGB4444 (2 << 16) -#define FIMC_REG_CIOCTRL_ORDER2P_SHIFT 24 -#define FIMC_REG_CIOCTRL_ORDER2P_MASK (3 << 24) -#define FIMC_REG_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24) - -/* Pre-scaler control 1 */ -#define FIMC_REG_CISCPRERATIO 0x50 - -#define FIMC_REG_CISCPREDST 0x54 - -/* Main scaler control */ -#define FIMC_REG_CISCCTRL 0x58 -#define FIMC_REG_CISCCTRL_SCALERBYPASS BIT(31) -#define FIMC_REG_CISCCTRL_SCALEUP_H BIT(30) -#define FIMC_REG_CISCCTRL_SCALEUP_V BIT(29) -#define FIMC_REG_CISCCTRL_CSCR2Y_WIDE BIT(28) -#define FIMC_REG_CISCCTRL_CSCY2R_WIDE BIT(27) -#define FIMC_REG_CISCCTRL_LCDPATHEN_FIFO BIT(26) -#define FIMC_REG_CISCCTRL_INTERLACE BIT(25) -#define FIMC_REG_CISCCTRL_SCALERSTART BIT(15) -#define FIMC_REG_CISCCTRL_INRGB_FMT_RGB565 (0 << 13) -#define FIMC_REG_CISCCTRL_INRGB_FMT_RGB666 (1 << 13) -#define FIMC_REG_CISCCTRL_INRGB_FMT_RGB888 (2 << 13) -#define FIMC_REG_CISCCTRL_INRGB_FMT_MASK (3 << 13) -#define FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11) -#define FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11) -#define FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11) -#define FIMC_REG_CISCCTRL_OUTRGB_FMT_MASK (3 << 11) -#define FIMC_REG_CISCCTRL_RGB_EXT BIT(10) -#define FIMC_REG_CISCCTRL_ONE2ONE BIT(9) -#define FIMC_REG_CISCCTRL_MHRATIO(x) ((x) << 16) -#define FIMC_REG_CISCCTRL_MVRATIO(x) ((x) << 0) -#define FIMC_REG_CISCCTRL_MHRATIO_MASK (0x1ff << 16) -#define FIMC_REG_CISCCTRL_MVRATIO_MASK (0x1ff << 0) -#define FIMC_REG_CISCCTRL_MHRATIO_EXT(x) (((x) >> 6) << 16) -#define FIMC_REG_CISCCTRL_MVRATIO_EXT(x) (((x) >> 6) << 0) - -/* Target area */ -#define FIMC_REG_CITAREA 0x5c -#define FIMC_REG_CITAREA_MASK 0x0fffffff - -/* General status */ -#define FIMC_REG_CISTATUS 0x64 -#define FIMC_REG_CISTATUS_OVFIY BIT(31) -#define FIMC_REG_CISTATUS_OVFICB BIT(30) -#define FIMC_REG_CISTATUS_OVFICR BIT(29) -#define FIMC_REG_CISTATUS_VSYNC BIT(28) -#define FIMC_REG_CISTATUS_FRAMECNT_MASK (3 << 26) -#define FIMC_REG_CISTATUS_FRAMECNT_SHIFT 26 -#define FIMC_REG_CISTATUS_WINOFF_EN BIT(25) -#define FIMC_REG_CISTATUS_IMGCPT_EN BIT(22) -#define FIMC_REG_CISTATUS_IMGCPT_SCEN BIT(21) -#define FIMC_REG_CISTATUS_VSYNC_A BIT(20) -#define FIMC_REG_CISTATUS_VSYNC_B BIT(19) -#define FIMC_REG_CISTATUS_OVRLB BIT(18) -#define FIMC_REG_CISTATUS_FRAME_END BIT(17) -#define FIMC_REG_CISTATUS_LASTCAPT_END BIT(16) -#define FIMC_REG_CISTATUS_VVALID_A BIT(15) -#define FIMC_REG_CISTATUS_VVALID_B BIT(14) - -/* Indexes to the last and the currently processed buffer. */ -#define FIMC_REG_CISTATUS2 0x68 - -/* Image capture control */ -#define FIMC_REG_CIIMGCPT 0xc0 -#define FIMC_REG_CIIMGCPT_IMGCPTEN BIT(31) -#define FIMC_REG_CIIMGCPT_IMGCPTEN_SC BIT(30) -#define FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE BIT(25) -#define FIMC_REG_CIIMGCPT_CPT_FRMOD_CNT BIT(18) - -/* Frame capture sequence */ -#define FIMC_REG_CICPTSEQ 0xc4 - -/* Image effect */ -#define FIMC_REG_CIIMGEFF 0xd0 -#define FIMC_REG_CIIMGEFF_IE_ENABLE BIT(30) -#define FIMC_REG_CIIMGEFF_IE_SC_BEFORE (0 << 29) -#define FIMC_REG_CIIMGEFF_IE_SC_AFTER (1 << 29) -#define FIMC_REG_CIIMGEFF_FIN_BYPASS (0 << 26) -#define FIMC_REG_CIIMGEFF_FIN_ARBITRARY (1 << 26) -#define FIMC_REG_CIIMGEFF_FIN_NEGATIVE (2 << 26) -#define FIMC_REG_CIIMGEFF_FIN_ARTFREEZE (3 << 26) -#define FIMC_REG_CIIMGEFF_FIN_EMBOSSING (4 << 26) -#define FIMC_REG_CIIMGEFF_FIN_SILHOUETTE (5 << 26) -#define FIMC_REG_CIIMGEFF_FIN_MASK (7 << 26) -#define FIMC_REG_CIIMGEFF_PAT_CBCR_MASK ((0xff << 13) | 0xff) - -/* Input DMA Y/Cb/Cr plane start address 0/1 */ -#define FIMC_REG_CIIYSA(n) (0xd4 + (n) * 0x70) -#define FIMC_REG_CIICBSA(n) (0xd8 + (n) * 0x70) -#define FIMC_REG_CIICRSA(n) (0xdc + (n) * 0x70) - -/* Real input DMA image size */ -#define FIMC_REG_CIREAL_ISIZE 0xf8 -#define FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN BIT(31) -#define FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS BIT(30) - -/* Input DMA control */ -#define FIMC_REG_MSCTRL 0xfc -#define FIMC_REG_MSCTRL_IN_BURST_COUNT_MASK (0xf << 24) -#define FIMC_REG_MSCTRL_2P_IN_ORDER_MASK (3 << 16) -#define FIMC_REG_MSCTRL_2P_IN_ORDER_SHIFT 16 -#define FIMC_REG_MSCTRL_C_INT_IN_3PLANE (0 << 15) -#define FIMC_REG_MSCTRL_C_INT_IN_2PLANE (1 << 15) -#define FIMC_REG_MSCTRL_C_INT_IN_MASK (1 << 15) -#define FIMC_REG_MSCTRL_FLIP_SHIFT 13 -#define FIMC_REG_MSCTRL_FLIP_MASK (3 << 13) -#define FIMC_REG_MSCTRL_FLIP_NORMAL (0 << 13) -#define FIMC_REG_MSCTRL_FLIP_X_MIRROR (1 << 13) -#define FIMC_REG_MSCTRL_FLIP_Y_MIRROR (2 << 13) -#define FIMC_REG_MSCTRL_FLIP_180 (3 << 13) -#define FIMC_REG_MSCTRL_FIFO_CTRL_FULL BIT(12) -#define FIMC_REG_MSCTRL_ORDER422_SHIFT 4 -#define FIMC_REG_MSCTRL_ORDER422_CRYCBY (0 << 4) -#define FIMC_REG_MSCTRL_ORDER422_YCRYCB (1 << 4) -#define FIMC_REG_MSCTRL_ORDER422_CBYCRY (2 << 4) -#define FIMC_REG_MSCTRL_ORDER422_YCBYCR (3 << 4) -#define FIMC_REG_MSCTRL_ORDER422_MASK (3 << 4) -#define FIMC_REG_MSCTRL_INPUT_EXTCAM (0 << 3) -#define FIMC_REG_MSCTRL_INPUT_MEMORY BIT(3) -#define FIMC_REG_MSCTRL_INPUT_MASK BIT(3) -#define FIMC_REG_MSCTRL_INFORMAT_YCBCR420 (0 << 1) -#define FIMC_REG_MSCTRL_INFORMAT_YCBCR422 (1 << 1) -#define FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P (2 << 1) -#define FIMC_REG_MSCTRL_INFORMAT_RGB (3 << 1) -#define FIMC_REG_MSCTRL_INFORMAT_MASK (3 << 1) -#define FIMC_REG_MSCTRL_ENVID BIT(0) -#define FIMC_REG_MSCTRL_IN_BURST_COUNT(x) ((x) << 24) - -/* Output DMA Y/Cb/Cr offset */ -#define FIMC_REG_CIOYOFF 0x168 -#define FIMC_REG_CIOCBOFF 0x16c -#define FIMC_REG_CIOCROFF 0x170 - -/* Input DMA Y/Cb/Cr offset */ -#define FIMC_REG_CIIYOFF 0x174 -#define FIMC_REG_CIICBOFF 0x178 -#define FIMC_REG_CIICROFF 0x17c - -/* Input DMA original image size */ -#define FIMC_REG_ORGISIZE 0x180 - -/* Output DMA original image size */ -#define FIMC_REG_ORGOSIZE 0x184 - -/* Real output DMA image size (extension register) */ -#define FIMC_REG_CIEXTEN 0x188 -#define FIMC_REG_CIEXTEN_MHRATIO_EXT(x) (((x) & 0x3f) << 10) -#define FIMC_REG_CIEXTEN_MVRATIO_EXT(x) ((x) & 0x3f) -#define FIMC_REG_CIEXTEN_MHRATIO_EXT_MASK (0x3f << 10) -#define FIMC_REG_CIEXTEN_MVRATIO_EXT_MASK 0x3f - -#define FIMC_REG_CIDMAPARAM 0x18c -#define FIMC_REG_CIDMAPARAM_R_LINEAR (0 << 29) -#define FIMC_REG_CIDMAPARAM_R_64X32 (3 << 29) -#define FIMC_REG_CIDMAPARAM_W_LINEAR (0 << 13) -#define FIMC_REG_CIDMAPARAM_W_64X32 (3 << 13) -#define FIMC_REG_CIDMAPARAM_TILE_MASK ((3 << 29) | (3 << 13)) - -/* MIPI CSI image format */ -#define FIMC_REG_CSIIMGFMT 0x194 -#define FIMC_REG_CSIIMGFMT_YCBCR422_8BIT 0x1e -#define FIMC_REG_CSIIMGFMT_RAW8 0x2a -#define FIMC_REG_CSIIMGFMT_RAW10 0x2b -#define FIMC_REG_CSIIMGFMT_RAW12 0x2c -/* User defined formats. x = 0...16. */ -#define FIMC_REG_CSIIMGFMT_USER(x) (0x30 + x - 1) - -/* Output frame buffer sequence mask */ -#define FIMC_REG_CIFCNTSEQ 0x1fc - -/* SYSREG ISP Writeback register address offsets */ -#define SYSREG_ISPBLK 0x020c -#define SYSREG_ISPBLK_FIFORST_CAM_BLK BIT(7) - -#define SYSREG_CAMBLK 0x0218 -#define SYSREG_CAMBLK_FIFORST_ISP BIT(15) -#define SYSREG_CAMBLK_ISPWB_FULL_EN (7 << 20) - -/* - * Function declarations - */ -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_enable_capture(struct fimc_ctx *ctx); -void fimc_hw_set_effect(struct fimc_ctx *ctx); -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 *addr); -void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *addr, - int index); -int fimc_hw_set_camera_source(struct fimc_dev *fimc, - struct fimc_source_info *cam); -void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f); -int fimc_hw_set_camera_polarity(struct fimc_dev *fimc, - struct fimc_source_info *cam); -int fimc_hw_set_camera_type(struct fimc_dev *fimc, - struct fimc_source_info *cam); -void fimc_hw_clear_irq(struct fimc_dev *dev); -void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on); -void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on); -void fimc_hw_disable_capture(struct fimc_dev *dev); -s32 fimc_hw_get_frame_index(struct fimc_dev *dev); -s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev); -int fimc_hw_camblk_cfg_writeback(struct fimc_dev *fimc); -void fimc_activate_capture(struct fimc_ctx *ctx); -void fimc_deactivate_capture(struct fimc_dev *fimc); - -/** - * fimc_hw_set_dma_seq - configure output DMA buffer sequence - * @dev: fimc device - * @mask: bitmask for the DMA output buffer registers, set to 0 to skip buffer - * This function masks output DMA ring buffers, it allows to select which of - * the 32 available 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 + FIMC_REG_CIFCNTSEQ); -} - -#endif /* FIMC_REG_H_ */ diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c deleted file mode 100644 index 544b54e428c9..000000000000 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ /dev/null @@ -1,1604 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * S5P/EXYNOS4 SoC series camera host interface media device driver - * - * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. - * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#include <linux/bug.h> -#include <linux/clk.h> -#include <linux/clk-provider.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/of.h> -#include <linux/of_platform.h> -#include <linux/of_device.h> -#include <linux/of_graph.h> -#include <linux/pinctrl/consumer.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/types.h> -#include <linux/slab.h> -#include <media/v4l2-async.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-fwnode.h> -#include <media/media-device.h> -#include <media/drv-intf/exynos-fimc.h> - -#include "media-dev.h" -#include "fimc-core.h" -#include "fimc-is.h" -#include "fimc-lite.h" -#include "mipi-csis.h" - -/* Set up image sensor subdev -> FIMC capture node notifications. */ -static void __setup_sensor_notification(struct fimc_md *fmd, - struct v4l2_subdev *sensor, - struct v4l2_subdev *fimc_sd) -{ - struct fimc_source_info *src_inf; - struct fimc_sensor_info *md_si; - unsigned long flags; - - src_inf = v4l2_get_subdev_hostdata(sensor); - if (!src_inf || WARN_ON(fmd == NULL)) - return; - - md_si = source_to_sensor_info(src_inf); - spin_lock_irqsave(&fmd->slock, flags); - md_si->host = v4l2_get_subdevdata(fimc_sd); - spin_unlock_irqrestore(&fmd->slock, flags); -} - -/** - * fimc_pipeline_prepare - update pipeline information with subdevice pointers - * @p: fimc pipeline - * @me: media entity terminating the pipeline - * - * Caller holds the graph mutex. - */ -static void fimc_pipeline_prepare(struct fimc_pipeline *p, - struct media_entity *me) -{ - struct fimc_md *fmd = entity_to_fimc_mdev(me); - struct v4l2_subdev *sd; - struct v4l2_subdev *sensor = NULL; - int i; - - for (i = 0; i < IDX_MAX; i++) - p->subdevs[i] = NULL; - - while (1) { - struct media_pad *pad = NULL; - - /* Find remote source pad */ - for (i = 0; i < me->num_pads; i++) { - struct media_pad *spad = &me->pads[i]; - if (!(spad->flags & MEDIA_PAD_FL_SINK)) - continue; - pad = media_entity_remote_pad(spad); - if (pad) - break; - } - - if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) - break; - sd = media_entity_to_v4l2_subdev(pad->entity); - - switch (sd->grp_id) { - case GRP_ID_SENSOR: - sensor = sd; - fallthrough; - case GRP_ID_FIMC_IS_SENSOR: - p->subdevs[IDX_SENSOR] = sd; - break; - case GRP_ID_CSIS: - p->subdevs[IDX_CSIS] = sd; - break; - case GRP_ID_FLITE: - p->subdevs[IDX_FLITE] = sd; - break; - case GRP_ID_FIMC: - p->subdevs[IDX_FIMC] = sd; - break; - case GRP_ID_FIMC_IS: - p->subdevs[IDX_IS_ISP] = sd; - break; - default: - break; - } - me = &sd->entity; - if (me->num_pads == 1) - break; - } - - if (sensor && p->subdevs[IDX_FIMC]) - __setup_sensor_notification(fmd, sensor, p->subdevs[IDX_FIMC]); -} - -/** - * __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 - * @p: fimc device terminating the pipeline - * @on: true to power on, false to power off - * - * Needs to be called with the graph mutex held. - */ -static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool on) -{ - static const u8 seq[2][IDX_MAX - 1] = { - { IDX_IS_ISP, IDX_SENSOR, IDX_CSIS, IDX_FLITE }, - { IDX_CSIS, IDX_FLITE, IDX_SENSOR, IDX_IS_ISP }, - }; - int i, ret = 0; - - if (p->subdevs[IDX_SENSOR] == NULL) - return -ENXIO; - - for (i = 0; i < IDX_MAX - 1; i++) { - unsigned int idx = seq[on][i]; - - ret = __subdev_set_power(p->subdevs[idx], on); - - - if (ret < 0 && ret != -ENXIO) - goto error; - } - return 0; -error: - for (; i >= 0; i--) { - unsigned int idx = seq[on][i]; - __subdev_set_power(p->subdevs[idx], !on); - } - return ret; -} - -/** - * __fimc_pipeline_enable - enable power of all pipeline subdevs - * and the sensor clock - * @ep: video pipeline structure - * @fmd: fimc media device - * - * Called with the graph mutex held. - */ -static int __fimc_pipeline_enable(struct exynos_media_pipeline *ep, - struct fimc_md *fmd) -{ - struct fimc_pipeline *p = to_fimc_pipeline(ep); - int ret; - - /* Enable PXLASYNC clock if this pipeline includes FIMC-IS */ - if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) { - ret = clk_prepare_enable(fmd->wbclk[CLK_IDX_WB_B]); - if (ret < 0) - return ret; - } - - ret = fimc_pipeline_s_power(p, 1); - if (!ret) - return 0; - - if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) - clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]); - - return ret; -} - -/** - * __fimc_pipeline_open - update the pipeline information, enable power - * of all pipeline subdevs and the sensor clock - * @ep: fimc device terminating the pipeline - * @me: media entity to start graph walk with - * @prepare: true to walk the current pipeline and acquire all subdevs - * - * Called with the graph mutex held. - */ -static int __fimc_pipeline_open(struct exynos_media_pipeline *ep, - struct media_entity *me, bool prepare) -{ - struct fimc_md *fmd = entity_to_fimc_mdev(me); - struct fimc_pipeline *p = to_fimc_pipeline(ep); - struct v4l2_subdev *sd; - - if (WARN_ON(p == NULL || me == NULL)) - return -EINVAL; - - if (prepare) - fimc_pipeline_prepare(p, me); - - sd = p->subdevs[IDX_SENSOR]; - if (sd == NULL) { - pr_warn("%s(): No sensor subdev\n", __func__); - /* - * Pipeline open cannot fail so as to make it possible - * for the user space to configure the pipeline. - */ - return 0; - } - - return __fimc_pipeline_enable(ep, fmd); -} - -/** - * __fimc_pipeline_close - disable the sensor clock and pipeline power - * @ep: fimc device terminating the pipeline - * - * Disable power of all subdevs and turn the external sensor clock off. - */ -static int __fimc_pipeline_close(struct exynos_media_pipeline *ep) -{ - struct fimc_pipeline *p = to_fimc_pipeline(ep); - struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL; - struct fimc_md *fmd; - int ret; - - if (sd == NULL) { - pr_warn("%s(): No sensor subdev\n", __func__); - return 0; - } - - ret = fimc_pipeline_s_power(p, 0); - - fmd = entity_to_fimc_mdev(&sd->entity); - - /* Disable PXLASYNC clock if this pipeline includes FIMC-IS */ - if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) - clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]); - - return ret == -ENXIO ? 0 : ret; -} - -/** - * __fimc_pipeline_s_stream - call s_stream() on pipeline subdevs - * @ep: video pipeline structure - * @on: passed as the s_stream() callback argument - */ -static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on) -{ - static const u8 seq[2][IDX_MAX] = { - { IDX_FIMC, IDX_SENSOR, IDX_IS_ISP, IDX_CSIS, IDX_FLITE }, - { IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP }, - }; - struct fimc_pipeline *p = to_fimc_pipeline(ep); - enum fimc_subdev_index sd_id; - int i, ret = 0; - - if (p->subdevs[IDX_SENSOR] == NULL) { - struct fimc_md *fmd; - struct v4l2_subdev *sd = p->subdevs[IDX_CSIS]; - - if (!sd) - sd = p->subdevs[IDX_FIMC]; - - if (!sd) { - /* - * If neither CSIS nor FIMC was set up, - * it's impossible to have any sensors - */ - return -ENODEV; - } - - fmd = entity_to_fimc_mdev(&sd->entity); - - if (!fmd->user_subdev_api) { - /* - * Sensor must be already discovered if we - * aren't in the user_subdev_api mode - */ - return -ENODEV; - } - - /* Get pipeline sink entity */ - if (p->subdevs[IDX_FIMC]) - sd_id = IDX_FIMC; - else if (p->subdevs[IDX_IS_ISP]) - sd_id = IDX_IS_ISP; - else if (p->subdevs[IDX_FLITE]) - sd_id = IDX_FLITE; - else - return -ENODEV; - - /* - * Sensor could have been linked between open and STREAMON - - * check if this is the case. - */ - fimc_pipeline_prepare(p, &p->subdevs[sd_id]->entity); - - if (p->subdevs[IDX_SENSOR] == NULL) - return -ENODEV; - - ret = __fimc_pipeline_enable(ep, fmd); - if (ret < 0) - return ret; - - } - - for (i = 0; i < IDX_MAX; i++) { - unsigned int idx = seq[on][i]; - - ret = v4l2_subdev_call(p->subdevs[idx], video, s_stream, on); - - if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) - goto error; - } - - return 0; -error: - fimc_pipeline_s_power(p, !on); - for (; i >= 0; i--) { - unsigned int idx = seq[on][i]; - v4l2_subdev_call(p->subdevs[idx], video, s_stream, !on); - } - return ret; -} - -/* Media pipeline operations for the FIMC/FIMC-LITE video device driver */ -static const struct exynos_media_pipeline_ops fimc_pipeline_ops = { - .open = __fimc_pipeline_open, - .close = __fimc_pipeline_close, - .set_stream = __fimc_pipeline_s_stream, -}; - -static struct exynos_media_pipeline *fimc_md_pipeline_create( - struct fimc_md *fmd) -{ - struct fimc_pipeline *p; - - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return NULL; - - list_add_tail(&p->list, &fmd->pipelines); - - p->ep.ops = &fimc_pipeline_ops; - return &p->ep; -} - -static void fimc_md_pipelines_free(struct fimc_md *fmd) -{ - while (!list_empty(&fmd->pipelines)) { - struct fimc_pipeline *p; - - p = list_entry(fmd->pipelines.next, typeof(*p), list); - list_del(&p->list); - kfree(p); - } -} - -static int fimc_md_parse_one_endpoint(struct fimc_md *fmd, - struct device_node *ep) -{ - int index = fmd->num_sensors; - struct fimc_source_info *pd = &fmd->sensor[index].pdata; - struct device_node *rem, *np; - struct v4l2_async_subdev *asd; - struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 }; - int ret; - - ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &endpoint); - if (ret) { - of_node_put(ep); - return ret; - } - - if (WARN_ON(endpoint.base.port == 0) || index >= FIMC_MAX_SENSORS) { - of_node_put(ep); - return -EINVAL; - } - - pd->mux_id = (endpoint.base.port - 1) & 0x1; - - rem = of_graph_get_remote_port_parent(ep); - if (rem == NULL) { - v4l2_info(&fmd->v4l2_dev, "Remote device at %pOF not found\n", - ep); - of_node_put(ep); - return 0; - } - - if (fimc_input_is_parallel(endpoint.base.port)) { - if (endpoint.bus_type == V4L2_MBUS_PARALLEL) - pd->sensor_bus_type = FIMC_BUS_TYPE_ITU_601; - else - pd->sensor_bus_type = FIMC_BUS_TYPE_ITU_656; - pd->flags = endpoint.bus.parallel.flags; - } else if (fimc_input_is_mipi_csi(endpoint.base.port)) { - /* - * MIPI CSI-2: only input mux selection and - * the sensor's clock frequency is needed. - */ - pd->sensor_bus_type = FIMC_BUS_TYPE_MIPI_CSI2; - } else { - v4l2_err(&fmd->v4l2_dev, "Wrong port id (%u) at node %pOF\n", - endpoint.base.port, rem); - } - /* - * For FIMC-IS handled sensors, that are placed under i2c-isp device - * node, FIMC is connected to the FIMC-IS through its ISP Writeback - * input. Sensors are attached to the FIMC-LITE hostdata interface - * directly or through MIPI-CSIS, depending on the external media bus - * used. This needs to be handled in a more reliable way, not by just - * checking parent's node name. - */ - np = of_get_parent(rem); - of_node_put(rem); - - if (of_node_name_eq(np, "i2c-isp")) - pd->fimc_bus_type = FIMC_BUS_TYPE_ISP_WRITEBACK; - else - pd->fimc_bus_type = pd->sensor_bus_type; - of_node_put(np); - - if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) { - of_node_put(ep); - return -EINVAL; - } - - asd = v4l2_async_nf_add_fwnode_remote(&fmd->subdev_notifier, - of_fwnode_handle(ep), - struct v4l2_async_subdev); - - of_node_put(ep); - - if (IS_ERR(asd)) - return PTR_ERR(asd); - - fmd->sensor[index].asd = asd; - fmd->num_sensors++; - - return 0; -} - -/* Parse port node and register as a sub-device any sensor specified there. */ -static int fimc_md_parse_port_node(struct fimc_md *fmd, - struct device_node *port) -{ - struct device_node *ep; - int ret; - - for_each_child_of_node(port, ep) { - ret = fimc_md_parse_one_endpoint(fmd, ep); - if (ret < 0) { - of_node_put(ep); - return ret; - } - } - - return 0; -} - -/* Register all SoC external sub-devices */ -static int fimc_md_register_sensor_entities(struct fimc_md *fmd) -{ - struct device_node *parent = fmd->pdev->dev.of_node; - struct device_node *ports = NULL; - struct device_node *node; - int ret; - - /* - * Runtime resume one of the FIMC entities to make sure - * the sclk_cam clocks are not globally disabled. - */ - if (!fmd->pmf) - return -ENXIO; - - ret = pm_runtime_resume_and_get(fmd->pmf); - if (ret < 0) - return ret; - - fmd->num_sensors = 0; - - /* Attach sensors linked to MIPI CSI-2 receivers */ - for_each_available_child_of_node(parent, node) { - struct device_node *port; - - if (!of_node_name_eq(node, "csis")) - continue; - /* The csis node can have only port subnode. */ - port = of_get_next_child(node, NULL); - if (!port) - continue; - - ret = fimc_md_parse_port_node(fmd, port); - of_node_put(port); - if (ret < 0) { - of_node_put(node); - goto cleanup; - } - } - - /* Attach sensors listed in the parallel-ports node */ - ports = of_get_child_by_name(parent, "parallel-ports"); - if (!ports) - goto rpm_put; - - for_each_child_of_node(ports, node) { - ret = fimc_md_parse_port_node(fmd, node); - if (ret < 0) { - of_node_put(node); - goto cleanup; - } - } - of_node_put(ports); - -rpm_put: - pm_runtime_put(fmd->pmf); - return 0; - -cleanup: - of_node_put(ports); - v4l2_async_nf_cleanup(&fmd->subdev_notifier); - pm_runtime_put(fmd->pmf); - return ret; -} - -static int __of_get_csis_id(struct device_node *np) -{ - u32 reg = 0; - - np = of_get_child_by_name(np, "port"); - if (!np) - return -EINVAL; - of_property_read_u32(np, "reg", ®); - of_node_put(np); - return reg - FIMC_INPUT_MIPI_CSI2_0; -} - -/* - * MIPI-CSIS, FIMC and FIMC-LITE platform devices registration. - */ -static int register_fimc_lite_entity(struct fimc_md *fmd, - struct fimc_lite *fimc_lite) -{ - struct v4l2_subdev *sd; - struct exynos_media_pipeline *ep; - int ret; - - if (WARN_ON(fimc_lite->index >= FIMC_LITE_MAX_DEVS || - fmd->fimc_lite[fimc_lite->index])) - return -EBUSY; - - sd = &fimc_lite->subdev; - sd->grp_id = GRP_ID_FLITE; - - ep = fimc_md_pipeline_create(fmd); - if (!ep) - return -ENOMEM; - - v4l2_set_subdev_hostdata(sd, ep); - - ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); - if (!ret) - fmd->fimc_lite[fimc_lite->index] = fimc_lite; - else - v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.LITE%d\n", - fimc_lite->index); - return ret; -} - -static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc) -{ - struct v4l2_subdev *sd; - struct exynos_media_pipeline *ep; - int ret; - - if (WARN_ON(fimc->id >= FIMC_MAX_DEVS || fmd->fimc[fimc->id])) - return -EBUSY; - - sd = &fimc->vid_cap.subdev; - sd->grp_id = GRP_ID_FIMC; - - ep = fimc_md_pipeline_create(fmd); - if (!ep) - return -ENOMEM; - - v4l2_set_subdev_hostdata(sd, ep); - - ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); - if (!ret) { - if (!fmd->pmf && fimc->pdev) - fmd->pmf = &fimc->pdev->dev; - fmd->fimc[fimc->id] = fimc; - fimc->vid_cap.user_subdev_api = fmd->user_subdev_api; - } else { - v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n", - fimc->id, ret); - } - return ret; -} - -static int register_csis_entity(struct fimc_md *fmd, - struct platform_device *pdev, - struct v4l2_subdev *sd) -{ - struct device_node *node = pdev->dev.of_node; - int id, ret; - - id = node ? __of_get_csis_id(node) : max(0, pdev->id); - - if (WARN_ON(id < 0 || id >= CSIS_MAX_ENTITIES)) - return -ENOENT; - - if (WARN_ON(fmd->csis[id].sd)) - return -EBUSY; - - sd->grp_id = GRP_ID_CSIS; - ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); - if (!ret) - fmd->csis[id].sd = sd; - else - v4l2_err(&fmd->v4l2_dev, - "Failed to register MIPI-CSIS.%d (%d)\n", id, ret); - return ret; -} - -static int register_fimc_is_entity(struct fimc_md *fmd, struct fimc_is *is) -{ - struct v4l2_subdev *sd = &is->isp.subdev; - struct exynos_media_pipeline *ep; - int ret; - - /* Allocate pipeline object for the ISP capture video node. */ - ep = fimc_md_pipeline_create(fmd); - if (!ep) - return -ENOMEM; - - v4l2_set_subdev_hostdata(sd, ep); - - ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); - if (ret) { - v4l2_err(&fmd->v4l2_dev, - "Failed to register FIMC-ISP (%d)\n", ret); - return ret; - } - - fmd->fimc_is = is; - return 0; -} - -static int fimc_md_register_platform_entity(struct fimc_md *fmd, - struct platform_device *pdev, - int plat_entity) -{ - struct device *dev = &pdev->dev; - int ret = -EPROBE_DEFER; - void *drvdata; - - /* Lock to ensure dev->driver won't change. */ - device_lock(dev); - - if (!dev->driver || !try_module_get(dev->driver->owner)) - goto dev_unlock; - - drvdata = dev_get_drvdata(dev); - /* Some subdev didn't probe successfully id drvdata is NULL */ - if (drvdata) { - switch (plat_entity) { - case IDX_FIMC: - ret = register_fimc_entity(fmd, drvdata); - break; - case IDX_FLITE: - ret = register_fimc_lite_entity(fmd, drvdata); - break; - case IDX_CSIS: - ret = register_csis_entity(fmd, pdev, drvdata); - break; - case IDX_IS_ISP: - ret = register_fimc_is_entity(fmd, drvdata); - break; - default: - ret = -ENODEV; - } - } - - module_put(dev->driver->owner); -dev_unlock: - device_unlock(dev); - if (ret == -EPROBE_DEFER) - dev_info(&fmd->pdev->dev, "deferring %s device registration\n", - dev_name(dev)); - else if (ret < 0) - dev_err(&fmd->pdev->dev, "%s device registration failed (%d)\n", - dev_name(dev), ret); - return ret; -} - -/* Register FIMC, FIMC-LITE and CSIS media entities */ -static int fimc_md_register_platform_entities(struct fimc_md *fmd, - struct device_node *parent) -{ - struct device_node *node; - int ret = 0; - - for_each_available_child_of_node(parent, node) { - struct platform_device *pdev; - int plat_entity = -1; - - pdev = of_find_device_by_node(node); - if (!pdev) - continue; - - /* If driver of any entity isn't ready try all again later. */ - if (of_node_name_eq(node, CSIS_OF_NODE_NAME)) - plat_entity = IDX_CSIS; - else if (of_node_name_eq(node, FIMC_IS_OF_NODE_NAME)) - plat_entity = IDX_IS_ISP; - else if (of_node_name_eq(node, FIMC_LITE_OF_NODE_NAME)) - plat_entity = IDX_FLITE; - else if (of_node_name_eq(node, FIMC_OF_NODE_NAME) && - !of_property_read_bool(node, "samsung,lcd-wb")) - plat_entity = IDX_FIMC; - - if (plat_entity >= 0) - ret = fimc_md_register_platform_entity(fmd, pdev, - plat_entity); - put_device(&pdev->dev); - if (ret < 0) { - of_node_put(node); - break; - } - } - - return ret; -} - -static void fimc_md_unregister_entities(struct fimc_md *fmd) -{ - int i; - - for (i = 0; i < FIMC_MAX_DEVS; i++) { - struct fimc_dev *dev = fmd->fimc[i]; - if (dev == NULL) - continue; - v4l2_device_unregister_subdev(&dev->vid_cap.subdev); - dev->vid_cap.ve.pipe = NULL; - fmd->fimc[i] = NULL; - } - for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { - struct fimc_lite *dev = fmd->fimc_lite[i]; - if (dev == NULL) - continue; - v4l2_device_unregister_subdev(&dev->subdev); - dev->ve.pipe = NULL; - fmd->fimc_lite[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; - } - - if (fmd->fimc_is) - v4l2_device_unregister_subdev(&fmd->fimc_is->isp.subdev); - - v4l2_info(&fmd->v4l2_dev, "Unregistered all entities\n"); -} - -/** - * __fimc_md_create_fimc_sink_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 - * @link_mask: bitmask of the fimc devices for which link should be enabled - */ -static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, - struct media_entity *source, - struct v4l2_subdev *sensor, - int pad, int link_mask) -{ - struct fimc_source_info *si = NULL; - struct media_entity *sink; - unsigned int flags = 0; - int i, ret = 0; - - if (sensor) { - si = v4l2_get_subdev_hostdata(sensor); - /* Skip direct FIMC links in the logical FIMC-IS sensor path */ - if (si && si->fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK) - ret = 1; - } - - for (i = 0; !ret && i < FIMC_MAX_DEVS; i++) { - if (!fmd->fimc[i]) - continue; - /* - * Some FIMC variants are not fitted with camera capture - * interface. Skip creating a link from sensor for those. - */ - if (!fmd->fimc[i]->variant->has_cam_if) - continue; - - flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0; - - sink = &fmd->fimc[i]->vid_cap.subdev.entity; - ret = media_create_pad_link(source, pad, sink, - FIMC_SD_PAD_SINK_CAM, 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]\n", - source->name, flags ? '=' : '-', sink->name); - } - - for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { - if (!fmd->fimc_lite[i]) - continue; - - sink = &fmd->fimc_lite[i]->subdev.entity; - ret = media_create_pad_link(source, pad, sink, - FLITE_SD_PAD_SINK, 0); - if (ret) - return ret; - - /* Notify FIMC-LITE subdev entity */ - ret = media_entity_call(sink, link_setup, &sink->pads[0], - &source->pads[pad], 0); - if (ret) - break; - - v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]\n", - source->name, sink->name); - } - return 0; -} - -/* Create links from FIMC-LITE source pads to other entities */ -static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) -{ - struct media_entity *source, *sink; - int i, ret = 0; - - for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { - struct fimc_lite *fimc = fmd->fimc_lite[i]; - - if (fimc == NULL) - continue; - - source = &fimc->subdev.entity; - sink = &fimc->ve.vdev.entity; - /* FIMC-LITE's subdev and video node */ - ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_DMA, - sink, 0, 0); - if (ret) - break; - /* Link from FIMC-LITE to IS-ISP subdev */ - sink = &fmd->fimc_is->isp.subdev.entity; - ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_ISP, - sink, 0, 0); - if (ret) - break; - } - - return ret; -} - -/* Create FIMC-IS links */ -static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd) -{ - struct fimc_isp *isp = &fmd->fimc_is->isp; - struct media_entity *source, *sink; - int i, ret; - - source = &isp->subdev.entity; - - for (i = 0; i < FIMC_MAX_DEVS; i++) { - if (fmd->fimc[i] == NULL) - continue; - - /* Link from FIMC-IS-ISP subdev to FIMC */ - sink = &fmd->fimc[i]->vid_cap.subdev.entity; - ret = media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_FIFO, - sink, FIMC_SD_PAD_SINK_FIFO, 0); - if (ret) - return ret; - } - - /* Link from FIMC-IS-ISP subdev to fimc-is-isp.capture video node */ - sink = &isp->video_capture.ve.vdev.entity; - - /* Skip this link if the fimc-is-isp video node driver isn't built-in */ - if (sink->num_pads == 0) - return 0; - - return media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_DMA, - sink, 0, 0); -} - -/** - * fimc_md_create_links - create default links between registered entities - * @fmd: fimc media device - * - * 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 *csi_sensors[CSIS_MAX_ENTITIES] = { NULL }; - struct v4l2_subdev *sensor, *csis; - struct fimc_source_info *pdata; - struct media_entity *source, *sink; - int i, pad, fimc_id = 0, ret = 0; - u32 flags, link_mask = 0; - - for (i = 0; i < fmd->num_sensors; i++) { - if (fmd->sensor[i].subdev == NULL) - continue; - - sensor = fmd->sensor[i].subdev; - pdata = v4l2_get_subdev_hostdata(sensor); - if (!pdata) - continue; - - source = NULL; - - switch (pdata->sensor_bus_type) { - case FIMC_BUS_TYPE_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; - - pad = sensor->entity.num_pads - 1; - ret = media_create_pad_link(&sensor->entity, pad, - &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]\n", - sensor->entity.name, csis->entity.name); - - source = NULL; - csi_sensors[pdata->mux_id] = sensor; - break; - - case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656: - source = &sensor->entity; - pad = 0; - break; - - default: - v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n", - pdata->sensor_bus_type); - return -EINVAL; - } - if (source == NULL) - continue; - - link_mask = 1 << fimc_id++; - ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor, - pad, link_mask); - } - - for (i = 0; i < CSIS_MAX_ENTITIES; i++) { - if (fmd->csis[i].sd == NULL) - continue; - - source = &fmd->csis[i].sd->entity; - pad = CSIS_PAD_SOURCE; - sensor = csi_sensors[i]; - - link_mask = 1 << fimc_id++; - ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor, - pad, link_mask); - } - - /* 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.ve.vdev.entity; - - ret = media_create_pad_link(source, FIMC_SD_PAD_SOURCE, - sink, 0, flags); - if (ret) - break; - } - - ret = __fimc_md_create_flite_source_links(fmd); - if (ret < 0) - return ret; - - if (fmd->use_isp) - ret = __fimc_md_create_fimc_is_links(fmd); - - return ret; -} - -/* - * The peripheral sensor and CAM_BLK (PIXELASYNCMx) clocks management. - */ -static void fimc_md_put_clocks(struct fimc_md *fmd) -{ - int i = FIMC_MAX_CAMCLKS; - - while (--i >= 0) { - if (IS_ERR(fmd->camclk[i].clock)) - continue; - clk_put(fmd->camclk[i].clock); - fmd->camclk[i].clock = ERR_PTR(-EINVAL); - } - - /* Writeback (PIXELASYNCMx) clocks */ - for (i = 0; i < FIMC_MAX_WBCLKS; i++) { - if (IS_ERR(fmd->wbclk[i])) - continue; - clk_put(fmd->wbclk[i]); - fmd->wbclk[i] = ERR_PTR(-EINVAL); - } -} - -static int fimc_md_get_clocks(struct fimc_md *fmd) -{ - struct device *dev = &fmd->pdev->dev; - char clk_name[32]; - struct clk *clock; - int i, ret = 0; - - for (i = 0; i < FIMC_MAX_CAMCLKS; i++) - fmd->camclk[i].clock = ERR_PTR(-EINVAL); - - for (i = 0; i < FIMC_MAX_CAMCLKS; i++) { - snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i); - clock = clk_get(dev, clk_name); - - if (IS_ERR(clock)) { - dev_err(dev, "Failed to get clock: %s\n", clk_name); - ret = PTR_ERR(clock); - break; - } - fmd->camclk[i].clock = clock; - } - if (ret) - fimc_md_put_clocks(fmd); - - if (!fmd->use_isp) - return 0; - /* - * For now get only PIXELASYNCM1 clock (Writeback B/ISP), - * leave PIXELASYNCM0 out for the LCD Writeback driver. - */ - fmd->wbclk[CLK_IDX_WB_A] = ERR_PTR(-EINVAL); - - for (i = CLK_IDX_WB_B; i < FIMC_MAX_WBCLKS; i++) { - snprintf(clk_name, sizeof(clk_name), "pxl_async%u", i); - clock = clk_get(dev, clk_name); - if (IS_ERR(clock)) { - v4l2_err(&fmd->v4l2_dev, "Failed to get clock: %s\n", - clk_name); - ret = PTR_ERR(clock); - break; - } - fmd->wbclk[i] = clock; - } - if (ret) - fimc_md_put_clocks(fmd); - - return ret; -} - -static int __fimc_md_modify_pipeline(struct media_entity *entity, bool enable) -{ - struct exynos_video_entity *ve; - struct fimc_pipeline *p; - struct video_device *vdev; - int ret; - - vdev = media_entity_to_video_device(entity); - if (vdev->entity.use_count == 0) - return 0; - - ve = vdev_to_exynos_video_entity(vdev); - p = to_fimc_pipeline(ve->pipe); - /* - * Nothing to do if we are disabling the pipeline, some link - * has been disconnected and p->subdevs array is cleared now. - */ - if (!enable && p->subdevs[IDX_SENSOR] == NULL) - return 0; - - if (enable) - ret = __fimc_pipeline_open(ve->pipe, entity, true); - else - ret = __fimc_pipeline_close(ve->pipe); - - if (ret == 0 && !enable) - memset(p->subdevs, 0, sizeof(p->subdevs)); - - return ret; -} - -/* Locking: called with entity->graph_obj.mdev->graph_mutex mutex held. */ -static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable, - struct media_graph *graph) -{ - struct media_entity *entity_err = entity; - int ret; - - /* - * Walk current graph and call the pipeline open/close routine for each - * opened video node that belongs to the graph of entities connected - * through active links. This is needed as we cannot power on/off the - * subdevs in random order. - */ - media_graph_walk_start(graph, entity); - - while ((entity = media_graph_walk_next(graph))) { - if (!is_media_entity_v4l2_video_device(entity)) - continue; - - ret = __fimc_md_modify_pipeline(entity, enable); - - if (ret < 0) - goto err; - } - - return 0; - -err: - media_graph_walk_start(graph, entity_err); - - while ((entity_err = media_graph_walk_next(graph))) { - if (!is_media_entity_v4l2_video_device(entity_err)) - continue; - - __fimc_md_modify_pipeline(entity_err, !enable); - - if (entity_err == entity) - break; - } - - return ret; -} - -static int fimc_md_link_notify(struct media_link *link, unsigned int flags, - unsigned int notification) -{ - struct media_graph *graph = - &container_of(link->graph_obj.mdev, struct fimc_md, - media_dev)->link_setup_graph; - struct media_entity *sink = link->sink->entity; - int ret = 0; - - /* Before link disconnection */ - if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) { - ret = media_graph_walk_init(graph, - link->graph_obj.mdev); - if (ret) - return ret; - if (!(flags & MEDIA_LNK_FL_ENABLED)) - ret = __fimc_md_modify_pipelines(sink, false, graph); -#if 0 - else - /* TODO: Link state change validation */ -#endif - /* After link activation */ - } else if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH) { - if (link->flags & MEDIA_LNK_FL_ENABLED) - ret = __fimc_md_modify_pipelines(sink, true, graph); - media_graph_walk_cleanup(graph); - } - - return ret ? -EPIPE : 0; -} - -static const struct media_device_ops fimc_md_ops = { - .link_notify = fimc_md_link_notify, -}; - -static ssize_t subdev_conf_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fimc_md *fmd = dev_get_drvdata(dev); - - if (fmd->user_subdev_api) - return strscpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE); - - return strscpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE); -} - -static ssize_t subdev_conf_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fimc_md *fmd = dev_get_drvdata(dev); - 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_RW(subdev_conf_mode); - -static int cam_clk_prepare(struct clk_hw *hw) -{ - struct cam_clk *camclk = to_cam_clk(hw); - - if (camclk->fmd->pmf == NULL) - return -ENODEV; - - return pm_runtime_resume_and_get(camclk->fmd->pmf); -} - -static void cam_clk_unprepare(struct clk_hw *hw) -{ - struct cam_clk *camclk = to_cam_clk(hw); - - if (camclk->fmd->pmf == NULL) - return; - - pm_runtime_put_sync(camclk->fmd->pmf); -} - -static const struct clk_ops cam_clk_ops = { - .prepare = cam_clk_prepare, - .unprepare = cam_clk_unprepare, -}; - -static void fimc_md_unregister_clk_provider(struct fimc_md *fmd) -{ - struct cam_clk_provider *cp = &fmd->clk_provider; - unsigned int i; - - if (cp->of_node) - of_clk_del_provider(cp->of_node); - - for (i = 0; i < cp->num_clocks; i++) - clk_unregister(cp->clks[i]); -} - -static int fimc_md_register_clk_provider(struct fimc_md *fmd) -{ - struct cam_clk_provider *cp = &fmd->clk_provider; - struct device *dev = &fmd->pdev->dev; - int i, ret; - - for (i = 0; i < FIMC_MAX_CAMCLKS; i++) { - struct cam_clk *camclk = &cp->camclk[i]; - struct clk_init_data init; - const char *p_name; - - ret = of_property_read_string_index(dev->of_node, - "clock-output-names", i, &init.name); - if (ret < 0) - break; - - p_name = __clk_get_name(fmd->camclk[i].clock); - - /* It's safe since clk_register() will duplicate the string. */ - init.parent_names = &p_name; - init.num_parents = 1; - init.ops = &cam_clk_ops; - init.flags = CLK_SET_RATE_PARENT; - camclk->hw.init = &init; - camclk->fmd = fmd; - - cp->clks[i] = clk_register(NULL, &camclk->hw); - if (IS_ERR(cp->clks[i])) { - dev_err(dev, "failed to register clock: %s (%ld)\n", - init.name, PTR_ERR(cp->clks[i])); - ret = PTR_ERR(cp->clks[i]); - goto err; - } - cp->num_clocks++; - } - - if (cp->num_clocks == 0) { - dev_warn(dev, "clk provider not registered\n"); - return 0; - } - - cp->clk_data.clks = cp->clks; - cp->clk_data.clk_num = cp->num_clocks; - cp->of_node = dev->of_node; - ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, - &cp->clk_data); - if (ret == 0) - return 0; -err: - fimc_md_unregister_clk_provider(fmd); - return ret; -} - -static int subdev_notifier_bound(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) -{ - struct fimc_md *fmd = notifier_to_fimc_md(notifier); - struct fimc_sensor_info *si = NULL; - int i; - - /* Find platform data for this sensor subdev */ - for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++) - if (fmd->sensor[i].asd && - fmd->sensor[i].asd->match.fwnode == - of_fwnode_handle(subdev->dev->of_node)) - si = &fmd->sensor[i]; - - if (si == NULL) - return -EINVAL; - - v4l2_set_subdev_hostdata(subdev, &si->pdata); - - if (si->pdata.fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK) - subdev->grp_id = GRP_ID_FIMC_IS_SENSOR; - else - subdev->grp_id = GRP_ID_SENSOR; - - si->subdev = subdev; - - v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n", - subdev->name, fmd->num_sensors); - - fmd->num_sensors++; - - return 0; -} - -static int subdev_notifier_complete(struct v4l2_async_notifier *notifier) -{ - struct fimc_md *fmd = notifier_to_fimc_md(notifier); - int ret; - - mutex_lock(&fmd->media_dev.graph_mutex); - - ret = fimc_md_create_links(fmd); - if (ret < 0) - goto unlock; - - ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev); -unlock: - mutex_unlock(&fmd->media_dev.graph_mutex); - if (ret < 0) - return ret; - - return media_device_register(&fmd->media_dev); -} - -static const struct v4l2_async_notifier_operations subdev_notifier_ops = { - .bound = subdev_notifier_bound, - .complete = subdev_notifier_complete, -}; - -static int fimc_md_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct v4l2_device *v4l2_dev; - struct pinctrl *pinctrl; - struct fimc_md *fmd; - int ret; - - fmd = devm_kzalloc(dev, sizeof(*fmd), GFP_KERNEL); - if (!fmd) - return -ENOMEM; - - spin_lock_init(&fmd->slock); - INIT_LIST_HEAD(&fmd->pipelines); - fmd->pdev = pdev; - - strscpy(fmd->media_dev.model, "Samsung S5P FIMC", - sizeof(fmd->media_dev.model)); - fmd->media_dev.ops = &fimc_md_ops; - fmd->media_dev.dev = dev; - - v4l2_dev = &fmd->v4l2_dev; - v4l2_dev->mdev = &fmd->media_dev; - v4l2_dev->notify = fimc_sensor_notify; - strscpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name)); - - fmd->use_isp = fimc_md_is_isp_available(dev->of_node); - fmd->user_subdev_api = true; - - media_device_init(&fmd->media_dev); - - ret = v4l2_device_register(dev, &fmd->v4l2_dev); - if (ret < 0) { - v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); - goto err_md; - } - - ret = fimc_md_get_clocks(fmd); - if (ret) - goto err_v4l2dev; - - pinctrl = devm_pinctrl_get(dev); - if (IS_ERR(pinctrl)) { - ret = PTR_ERR(pinctrl); - if (ret != EPROBE_DEFER) - dev_err(dev, "Failed to get pinctrl: %d\n", ret); - goto err_clk; - } - - platform_set_drvdata(pdev, fmd); - - v4l2_async_nf_init(&fmd->subdev_notifier); - - ret = fimc_md_register_platform_entities(fmd, dev->of_node); - if (ret) - goto err_clk; - - ret = fimc_md_register_sensor_entities(fmd); - if (ret) - goto err_m_ent; - - ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode); - if (ret) - goto err_cleanup; - /* - * FIMC platform devices need to be registered before the sclk_cam - * clocks provider, as one of these devices needs to be activated - * to enable the clock. - */ - ret = fimc_md_register_clk_provider(fmd); - if (ret < 0) { - v4l2_err(v4l2_dev, "clock provider registration failed\n"); - goto err_attr; - } - - if (fmd->num_sensors > 0) { - fmd->subdev_notifier.ops = &subdev_notifier_ops; - fmd->num_sensors = 0; - - ret = v4l2_async_nf_register(&fmd->v4l2_dev, - &fmd->subdev_notifier); - if (ret) - goto err_clk_p; - } - - return 0; - -err_clk_p: - fimc_md_unregister_clk_provider(fmd); -err_attr: - device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); -err_cleanup: - v4l2_async_nf_cleanup(&fmd->subdev_notifier); -err_m_ent: - fimc_md_unregister_entities(fmd); -err_clk: - fimc_md_put_clocks(fmd); -err_v4l2dev: - v4l2_device_unregister(&fmd->v4l2_dev); -err_md: - media_device_cleanup(&fmd->media_dev); - return ret; -} - -static int fimc_md_remove(struct platform_device *pdev) -{ - struct fimc_md *fmd = platform_get_drvdata(pdev); - - if (!fmd) - return 0; - - fimc_md_unregister_clk_provider(fmd); - v4l2_async_nf_unregister(&fmd->subdev_notifier); - v4l2_async_nf_cleanup(&fmd->subdev_notifier); - - v4l2_device_unregister(&fmd->v4l2_dev); - device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); - fimc_md_unregister_entities(fmd); - fimc_md_pipelines_free(fmd); - media_device_unregister(&fmd->media_dev); - media_device_cleanup(&fmd->media_dev); - fimc_md_put_clocks(fmd); - - return 0; -} - -static const struct platform_device_id fimc_driver_ids[] __always_unused = { - { .name = "s5p-fimc-md" }, - { }, -}; -MODULE_DEVICE_TABLE(platform, fimc_driver_ids); - -static const struct of_device_id fimc_md_of_match[] = { - { .compatible = "samsung,fimc" }, - { }, -}; -MODULE_DEVICE_TABLE(of, fimc_md_of_match); - -static struct platform_driver fimc_md_driver = { - .probe = fimc_md_probe, - .remove = fimc_md_remove, - .driver = { - .of_match_table = of_match_ptr(fimc_md_of_match), - .name = "s5p-fimc-md", - } -}; - -static 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); -} - -static 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/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h deleted file mode 100644 index 62ad5d7e035a..000000000000 --- a/drivers/media/platform/exynos4-is/media-dev.h +++ /dev/null @@ -1,201 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. - */ - -#ifndef FIMC_MDEVICE_H_ -#define FIMC_MDEVICE_H_ - -#include <linux/clk.h> -#include <linux/clk-provider.h> -#include <linux/platform_device.h> -#include <linux/mutex.h> -#include <linux/of.h> -#include <linux/pinctrl/consumer.h> -#include <media/media-device.h> -#include <media/media-entity.h> -#include <media/v4l2-device.h> -#include <media/v4l2-subdev.h> -#include <media/drv-intf/exynos-fimc.h> - -#include "fimc-core.h" -#include "fimc-lite.h" -#include "mipi-csis.h" - -#define FIMC_OF_NODE_NAME "fimc" -#define FIMC_LITE_OF_NODE_NAME "fimc-lite" -#define FIMC_IS_OF_NODE_NAME "fimc-is" -#define CSIS_OF_NODE_NAME "csis" - -#define FIMC_MAX_SENSORS 4 -#define FIMC_MAX_CAMCLKS 2 -#define DEFAULT_SENSOR_CLK_FREQ 24000000U - -/* LCD/ISP Writeback clocks (PIXELASYNCMx) */ -enum { - CLK_IDX_WB_A, - CLK_IDX_WB_B, - FIMC_MAX_WBCLKS -}; - -enum fimc_subdev_index { - IDX_SENSOR, - IDX_CSIS, - IDX_FLITE, - IDX_IS_ISP, - IDX_FIMC, - IDX_MAX, -}; - -/* - * This structure represents a chain of media entities, including a data - * source entity (e.g. an image sensor subdevice), a data capture entity - * - a video capture device node and any remaining entities. - */ -struct fimc_pipeline { - struct exynos_media_pipeline ep; - struct list_head list; - struct media_entity *vdev_entity; - struct v4l2_subdev *subdevs[IDX_MAX]; -}; - -#define to_fimc_pipeline(_ep) container_of(_ep, struct fimc_pipeline, ep) - -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 attributes passed as media device's platform data - * @asd: asynchronous subdev registration data structure - * @subdev: image sensor v4l2 subdev - * @host: fimc device the sensor is currently linked to - * - * This data structure applies to image sensor and the writeback subdevs. - */ -struct fimc_sensor_info { - struct fimc_source_info pdata; - struct v4l2_async_subdev *asd; - struct v4l2_subdev *subdev; - struct fimc_dev *host; -}; - -struct cam_clk { - struct clk_hw hw; - struct fimc_md *fmd; -}; -#define to_cam_clk(_hw) container_of(_hw, struct cam_clk, hw) - -/** - * 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 - * @wbclk: external writeback clock information - * @fimc_lite: array of registered fimc-lite devices - * @fimc: array of registered fimc devices - * @fimc_is: fimc-is data structure - * @use_isp: set to true when FIMC-IS subsystem is used - * @pmf: handle to the CAMCLK clock control FIMC helper device - * @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 - * @clk_provider: CAMCLK clock provider structure - * @subdev_notifier: notifier for the subdevs - * @user_subdev_api: true if subdevs are not configured by the host driver - * @slock: spinlock protecting @sensor array - * @pipelines: list of pipelines - * @link_setup_graph: graph iterator - */ -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 clk *wbclk[FIMC_MAX_WBCLKS]; - struct fimc_lite *fimc_lite[FIMC_LITE_MAX_DEVS]; - struct fimc_dev *fimc[FIMC_MAX_DEVS]; - struct fimc_is *fimc_is; - bool use_isp; - struct device *pmf; - struct media_device media_dev; - struct v4l2_device v4l2_dev; - struct platform_device *pdev; - - struct cam_clk_provider { - struct clk *clks[FIMC_MAX_CAMCLKS]; - struct clk_onecell_data clk_data; - struct device_node *of_node; - struct cam_clk camclk[FIMC_MAX_CAMCLKS]; - int num_clocks; - } clk_provider; - - struct v4l2_async_notifier subdev_notifier; - - bool user_subdev_api; - spinlock_t slock; - struct list_head pipelines; - struct media_graph link_setup_graph; -}; - -static inline -struct fimc_sensor_info *source_to_sensor_info(struct fimc_source_info *si) -{ - return container_of(si, struct fimc_sensor_info, pdata); -} - -static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me) -{ - return me->graph_obj.mdev == NULL ? NULL : - container_of(me->graph_obj.mdev, struct fimc_md, media_dev); -} - -static inline struct fimc_md *notifier_to_fimc_md(struct v4l2_async_notifier *n) -{ - return container_of(n, struct fimc_md, subdev_notifier); -} - -static inline void fimc_md_graph_lock(struct exynos_video_entity *ve) -{ - mutex_lock(&ve->vdev.entity.graph_obj.mdev->graph_mutex); -} - -static inline void fimc_md_graph_unlock(struct exynos_video_entity *ve) -{ - mutex_unlock(&ve->vdev.entity.graph_obj.mdev->graph_mutex); -} - -int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on); - -#ifdef CONFIG_OF -static inline bool fimc_md_is_isp_available(struct device_node *node) -{ - node = of_get_child_by_name(node, FIMC_IS_OF_NODE_NAME); - return node ? of_device_is_available(node) : false; -} -#else -#define fimc_md_is_isp_available(node) (false) -#endif /* CONFIG_OF */ - -static inline struct v4l2_subdev *__fimc_md_get_subdev( - struct exynos_media_pipeline *ep, - unsigned int index) -{ - struct fimc_pipeline *p = to_fimc_pipeline(ep); - - if (!p || index >= IDX_MAX) - return NULL; - else - return p->subdevs[index]; -} - -#endif diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c deleted file mode 100644 index 27a214936cb0..000000000000 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ /dev/null @@ -1,1037 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver - * - * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. - * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> - */ - -#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/of.h> -#include <linux/of_graph.h> -#include <linux/phy/phy.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/regulator/consumer.h> -#include <linux/sizes.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/videodev2.h> -#include <media/drv-intf/exynos-fimc.h> -#include <media/v4l2-fwnode.h> -#include <media/v4l2-subdev.h> - -#include "mipi-csis.h" - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Debug level (0-2)"); - -/* Register map definition */ - -/* CSIS global control */ -#define S5PCSIS_CTRL 0x00 -#define S5PCSIS_CTRL_DPDN_DEFAULT (0 << 31) -#define S5PCSIS_CTRL_DPDN_SWAP (1UL << 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_EVEN_BEFORE (1UL << 31) -#define S5PCSIS_INTMSK_EVEN_AFTER (1 << 30) -#define S5PCSIS_INTMSK_ODD_BEFORE (1 << 29) -#define S5PCSIS_INTMSK_ODD_AFTER (1 << 28) -#define S5PCSIS_INTMSK_FRAME_START (1 << 27) -#define S5PCSIS_INTMSK_FRAME_END (1 << 26) -#define S5PCSIS_INTMSK_ERR_SOT_HS (1 << 12) -#define S5PCSIS_INTMSK_ERR_LOST_FS (1 << 5) -#define S5PCSIS_INTMSK_ERR_LOST_FE (1 << 4) -#define S5PCSIS_INTMSK_ERR_OVER (1 << 3) -#define S5PCSIS_INTMSK_ERR_ECC (1 << 2) -#define S5PCSIS_INTMSK_ERR_CRC (1 << 1) -#define S5PCSIS_INTMSK_ERR_UNKNOWN (1 << 0) -#define S5PCSIS_INTMSK_EXYNOS4_EN_ALL 0xf000103f -#define S5PCSIS_INTMSK_EXYNOS5_EN_ALL 0xfc00103f - -/* Interrupt source */ -#define S5PCSIS_INTSRC 0x14 -#define S5PCSIS_INTSRC_EVEN_BEFORE (1UL << 31) -#define S5PCSIS_INTSRC_EVEN_AFTER (1 << 30) -#define S5PCSIS_INTSRC_EVEN (0x3 << 30) -#define S5PCSIS_INTSRC_ODD_BEFORE (1 << 29) -#define S5PCSIS_INTSRC_ODD_AFTER (1 << 28) -#define S5PCSIS_INTSRC_ODD (0x3 << 28) -#define S5PCSIS_INTSRC_NON_IMAGE_DATA (0xf << 28) -#define S5PCSIS_INTSRC_FRAME_START (1 << 27) -#define S5PCSIS_INTSRC_FRAME_END (1 << 26) -#define S5PCSIS_INTSRC_ERR_SOT_HS (0xf << 12) -#define S5PCSIS_INTSRC_ERR_LOST_FS (1 << 5) -#define S5PCSIS_INTSRC_ERR_LOST_FE (1 << 4) -#define S5PCSIS_INTSRC_ERR_OVER (1 << 3) -#define S5PCSIS_INTSRC_ERR_ECC (1 << 2) -#define S5PCSIS_INTSRC_ERR_CRC (1 << 1) -#define S5PCSIS_INTSRC_ERR_UNKNOWN (1 << 0) -#define S5PCSIS_INTSRC_ERRORS 0xf03f - -/* Pixel resolution */ -#define S5PCSIS_RESOL 0x2c -#define CSIS_MAX_PIX_WIDTH 0xffff -#define CSIS_MAX_PIX_HEIGHT 0xffff - -/* Non-image packet data buffers */ -#define S5PCSIS_PKTDATA_ODD 0x2000 -#define S5PCSIS_PKTDATA_EVEN 0x3000 -#define S5PCSIS_PKTDATA_SIZE SZ_4K - -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) -#define DEFAULT_SCLK_CSIS_FREQ 166000000UL - -static const char * const csis_supply_name[] = { - "vddcore", /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */ - "vddio", /* CSIS I/O and PLL (1.8V) supply */ -}; -#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name) - -enum { - ST_POWERED = 1, - ST_STREAMING = 2, - ST_SUSPENDED = 4, -}; - -struct s5pcsis_event { - u32 mask; - const char * const name; - unsigned int counter; -}; - -static const struct s5pcsis_event s5pcsis_events[] = { - /* Errors */ - { S5PCSIS_INTSRC_ERR_SOT_HS, "SOT Error" }, - { S5PCSIS_INTSRC_ERR_LOST_FS, "Lost Frame Start Error" }, - { S5PCSIS_INTSRC_ERR_LOST_FE, "Lost Frame End Error" }, - { S5PCSIS_INTSRC_ERR_OVER, "FIFO Overflow Error" }, - { S5PCSIS_INTSRC_ERR_ECC, "ECC Error" }, - { S5PCSIS_INTSRC_ERR_CRC, "CRC Error" }, - { S5PCSIS_INTSRC_ERR_UNKNOWN, "Unknown Error" }, - /* Non-image data receive events */ - { S5PCSIS_INTSRC_EVEN_BEFORE, "Non-image data before even frame" }, - { S5PCSIS_INTSRC_EVEN_AFTER, "Non-image data after even frame" }, - { S5PCSIS_INTSRC_ODD_BEFORE, "Non-image data before odd frame" }, - { S5PCSIS_INTSRC_ODD_AFTER, "Non-image data after odd frame" }, - /* Frame start/end */ - { S5PCSIS_INTSRC_FRAME_START, "Frame Start" }, - { S5PCSIS_INTSRC_FRAME_END, "Frame End" }, -}; -#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events) - -struct csis_pktbuf { - u32 *data; - unsigned int len; -}; - -struct csis_drvdata { - /* Mask of all used interrupts in S5PCSIS_INTMSK register */ - u32 interrupt_mask; -}; - -/** - * 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 - * @index: the hardware instance index - * @pdev: CSIS platform device - * @phy: pointer to the CSIS generic PHY - * @regs: mmapped I/O registers memory - * @supplies: CSIS regulator supplies - * @clock: CSIS clocks - * @irq: requested s5p-mipi-csis irq number - * @interrupt_mask: interrupt mask of the all used interrupts - * @flags: the state variable for power and streaming control - * @clk_frequency: device bus clock frequency - * @hs_settle: HS-RX settle time - * @num_lanes: number of MIPI-CSI data lanes used - * @max_num_lanes: maximum number of MIPI-CSI data lanes supported - * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM - * @csis_fmt: current CSIS pixel format - * @format: common media bus format for the source and sink pad - * @slock: spinlock protecting structure members below - * @pkt_buf: the frame embedded (non-image) data buffer - * @events: MIPI-CSIS event (error) counters - */ -struct csis_state { - struct mutex lock; - struct media_pad pads[CSIS_PADS_NUM]; - struct v4l2_subdev sd; - u8 index; - struct platform_device *pdev; - struct phy *phy; - void __iomem *regs; - struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; - struct clk *clock[NUM_CSIS_CLOCKS]; - int irq; - u32 interrupt_mask; - u32 flags; - - u32 clk_frequency; - u32 hs_settle; - u32 num_lanes; - u32 max_num_lanes; - u8 wclk_ext; - - const struct csis_pix_format *csis_fmt; - struct v4l2_mbus_framefmt format; - - spinlock_t slock; - struct csis_pktbuf pkt_buf; - struct s5pcsis_event events[S5PCSIS_NUM_EVENTS]; -}; - -/** - * 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 - * @data_alignment: MIPI-CSI data alignment in bits - */ -struct csis_pix_format { - unsigned int pix_width_alignment; - u32 code; - u32 fmt_reg; - u8 data_alignment; -}; - -static const struct csis_pix_format s5pcsis_formats[] = { - { - .code = MEDIA_BUS_FMT_VYUY8_2X8, - .fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT, - .data_alignment = 32, - }, { - .code = MEDIA_BUS_FMT_JPEG_1X8, - .fmt_reg = S5PCSIS_CFG_FMT_USER(1), - .data_alignment = 32, - }, { - .code = MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8, - .fmt_reg = S5PCSIS_CFG_FMT_USER(1), - .data_alignment = 32, - }, { - .code = MEDIA_BUS_FMT_SGRBG8_1X8, - .fmt_reg = S5PCSIS_CFG_FMT_RAW8, - .data_alignment = 24, - }, { - .code = MEDIA_BUS_FMT_SGRBG10_1X10, - .fmt_reg = S5PCSIS_CFG_FMT_RAW10, - .data_alignment = 24, - }, { - .code = MEDIA_BUS_FMT_SGRBG12_1X12, - .fmt_reg = S5PCSIS_CFG_FMT_RAW12, - .data_alignment = 24, - } -}; - -#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); - if (on) - val |= state->interrupt_mask; - else - val &= ~state->interrupt_mask; - 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, mask; - - 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); - val &= ~S5PCSIS_DPHYCTRL_ENABLE; - if (on) { - mask = (1 << (state->num_lanes + 1)) - 1; - val |= (mask & 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: %#x, %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) -{ - u32 val; - - val = s5pcsis_read(state, S5PCSIS_CONFIG); - val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (state->num_lanes - 1); - s5pcsis_write(state, S5PCSIS_CONFIG, val); - - __s5pcsis_set_format(state); - s5pcsis_set_hsync_settle(state, state->hs_settle); - - val = s5pcsis_read(state, S5PCSIS_CTRL); - if (state->csis_fmt->data_alignment == 32) - val |= S5PCSIS_CTRL_ALIGN_32BIT; - else /* 24-bits */ - val &= ~S5PCSIS_CTRL_ALIGN_32BIT; - - val &= ~S5PCSIS_CTRL_WCLK_EXTCLK; - if (state->wclk_ext) - 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(state->clock[i])) - continue; - clk_unprepare(state->clock[i]); - clk_put(state->clock[i]); - state->clock[i] = ERR_PTR(-EINVAL); - } -} - -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] = ERR_PTR(-EINVAL); - - for (i = 0; i < NUM_CSIS_CLOCKS; i++) { - state->clock[i] = clk_get(dev, csi_clock_name[i]); - if (IS_ERR(state->clock[i])) { - ret = PTR_ERR(state->clock[i]); - goto err; - } - ret = clk_prepare(state->clock[i]); - if (ret < 0) { - clk_put(state->clock[i]); - state->clock[i] = ERR_PTR(-EINVAL); - goto err; - } - } - return 0; -err: - s5pcsis_clk_put(state); - dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]); - return ret; -} - -static void dump_regs(struct csis_state *state, const char *label) -{ - struct { - u32 offset; - const char * const name; - } registers[] = { - { 0x00, "CTRL" }, - { 0x04, "DPHYCTRL" }, - { 0x08, "CONFIG" }, - { 0x0c, "DPHYSTS" }, - { 0x10, "INTMSK" }, - { 0x2c, "RESOL" }, - { 0x38, "SDW_CONFIG" }, - }; - u32 i; - - v4l2_info(&state->sd, "--- %s ---\n", label); - - for (i = 0; i < ARRAY_SIZE(registers); i++) { - u32 cfg = s5pcsis_read(state, registers[i].offset); - v4l2_info(&state->sd, "%10s: 0x%08x\n", registers[i].name, cfg); - } -} - -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); -} - -static void s5pcsis_clear_counters(struct csis_state *state) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&state->slock, flags); - for (i = 0; i < S5PCSIS_NUM_EVENTS; i++) - state->events[i].counter = 0; - spin_unlock_irqrestore(&state->slock, flags); -} - -static void s5pcsis_log_counters(struct csis_state *state, bool non_errors) -{ - int i = non_errors ? S5PCSIS_NUM_EVENTS : S5PCSIS_NUM_EVENTS - 4; - unsigned long flags; - - spin_lock_irqsave(&state->slock, flags); - - for (i--; i >= 0; i--) { - if (state->events[i].counter > 0 || debug) - v4l2_info(&state->sd, "%s events: %d\n", - state->events[i].name, - state->events[i].counter); - } - spin_unlock_irqrestore(&state->slock, flags); -} - -/* - * V4L2 subdev operations - */ -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_resume_and_get(dev); - - return pm_runtime_put_sync(dev); -} - -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) { - s5pcsis_clear_counters(state); - ret = pm_runtime_resume_and_get(&state->pdev->dev); - if (ret < 0) - 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; - if (debug > 0) - s5pcsis_log_counters(state, true); - } -unlock: - mutex_unlock(&state->lock); - if (!enable) - pm_runtime_put(&state->pdev->dev); - - return ret; -} - -static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - 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_state *sd_state, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return sd_state ? v4l2_subdev_get_try_format(&state->sd, - sd_state, 0) : NULL; - - return &state->format; -} - -static int s5pcsis_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - 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; - - mf = __s5pcsis_get_format(state, sd_state, 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_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct csis_state *state = sd_to_csis_state(sd); - struct v4l2_mbus_framefmt *mf; - - mf = __s5pcsis_get_format(state, sd_state, fmt->which); - if (!mf) - return -EINVAL; - - mutex_lock(&state->lock); - fmt->format = *mf; - mutex_unlock(&state->lock); - return 0; -} - -static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf, - unsigned int *size) -{ - struct csis_state *state = sd_to_csis_state(sd); - unsigned long flags; - - *size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE); - - spin_lock_irqsave(&state->slock, flags); - state->pkt_buf.data = buf; - state->pkt_buf.len = *size; - spin_unlock_irqrestore(&state->slock, flags); - - return 0; -} - -static int s5pcsis_log_status(struct v4l2_subdev *sd) -{ - struct csis_state *state = sd_to_csis_state(sd); - - mutex_lock(&state->lock); - s5pcsis_log_counters(state, true); - if (debug && (state->flags & ST_POWERED)) - dump_regs(state, __func__); - mutex_unlock(&state->lock); - return 0; -} - -static const struct v4l2_subdev_core_ops s5pcsis_core_ops = { - .s_power = s5pcsis_s_power, - .log_status = s5pcsis_log_status, -}; - -static const 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 const struct v4l2_subdev_video_ops s5pcsis_video_ops = { - .s_rx_buffer = s5pcsis_s_rx_buffer, - .s_stream = s5pcsis_s_stream, -}; - -static const 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; - struct csis_pktbuf *pktbuf = &state->pkt_buf; - unsigned long flags; - u32 status; - - status = s5pcsis_read(state, S5PCSIS_INTSRC); - spin_lock_irqsave(&state->slock, flags); - - if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) { - u32 offset; - - if (status & S5PCSIS_INTSRC_EVEN) - offset = S5PCSIS_PKTDATA_EVEN; - else - offset = S5PCSIS_PKTDATA_ODD; - - memcpy(pktbuf->data, (u8 __force *)state->regs + offset, - pktbuf->len); - pktbuf->data = NULL; - rmb(); - } - - /* Update the event/error counters */ - if ((status & S5PCSIS_INTSRC_ERRORS) || debug) { - int i; - for (i = 0; i < S5PCSIS_NUM_EVENTS; i++) { - if (!(status & state->events[i].mask)) - continue; - state->events[i].counter++; - v4l2_dbg(2, debug, &state->sd, "%s: %d\n", - state->events[i].name, - state->events[i].counter); - } - v4l2_dbg(2, debug, &state->sd, "status: %08x\n", status); - } - spin_unlock_irqrestore(&state->slock, flags); - - s5pcsis_write(state, S5PCSIS_INTSRC, status); - return IRQ_HANDLED; -} - -static int s5pcsis_parse_dt(struct platform_device *pdev, - struct csis_state *state) -{ - struct device_node *node = pdev->dev.of_node; - struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 }; - int ret; - - if (of_property_read_u32(node, "clock-frequency", - &state->clk_frequency)) - state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ; - if (of_property_read_u32(node, "bus-width", - &state->max_num_lanes)) - return -EINVAL; - - node = of_graph_get_next_endpoint(node, NULL); - if (!node) { - dev_err(&pdev->dev, "No port node at %pOF\n", - pdev->dev.of_node); - return -EINVAL; - } - /* Get port node and validate MIPI-CSI channel id. */ - ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &endpoint); - if (ret) - goto err; - - state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0; - if (state->index >= CSIS_MAX_ENTITIES) { - ret = -ENXIO; - goto err; - } - - /* Get MIPI CSI-2 bus configuration from the endpoint node. */ - of_property_read_u32(node, "samsung,csis-hs-settle", - &state->hs_settle); - state->wclk_ext = of_property_read_bool(node, - "samsung,csis-wclk"); - - state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes; - -err: - of_node_put(node); - return ret; -} - -static int s5pcsis_pm_resume(struct device *dev, bool runtime); -static const struct of_device_id s5pcsis_of_match[]; - -static int s5pcsis_probe(struct platform_device *pdev) -{ - const struct of_device_id *of_id; - const struct csis_drvdata *drv_data; - struct device *dev = &pdev->dev; - struct csis_state *state; - int ret = -ENOMEM; - int i; - - state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; - - mutex_init(&state->lock); - spin_lock_init(&state->slock); - state->pdev = pdev; - - of_id = of_match_node(s5pcsis_of_match, dev->of_node); - if (WARN_ON(of_id == NULL)) - return -EINVAL; - - drv_data = of_id->data; - state->interrupt_mask = drv_data->interrupt_mask; - - ret = s5pcsis_parse_dt(pdev, state); - if (ret < 0) - return ret; - - if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) { - dev_err(dev, "Unsupported number of data lanes: %d (max. %d)\n", - state->num_lanes, state->max_num_lanes); - return -EINVAL; - } - - state->phy = devm_phy_get(dev, "csis"); - if (IS_ERR(state->phy)) - return PTR_ERR(state->phy); - - state->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(state->regs)) - return PTR_ERR(state->regs); - - state->irq = platform_get_irq(pdev, 0); - if (state->irq < 0) - return state->irq; - - for (i = 0; i < CSIS_NUM_SUPPLIES; i++) - state->supplies[i].supply = csis_supply_name[i]; - - ret = devm_regulator_bulk_get(dev, CSIS_NUM_SUPPLIES, - state->supplies); - if (ret) - return ret; - - ret = s5pcsis_clk_get(state); - if (ret < 0) - return ret; - - if (state->clk_frequency) - ret = clk_set_rate(state->clock[CSIS_CLK_MUX], - state->clk_frequency); - else - dev_WARN(dev, "No clock frequency specified!\n"); - if (ret < 0) - goto e_clkput; - - ret = clk_enable(state->clock[CSIS_CLK_MUX]); - if (ret < 0) - goto e_clkput; - - ret = devm_request_irq(dev, state->irq, s5pcsis_irq_handler, - 0, dev_name(dev), state); - if (ret) { - dev_err(dev, "Interrupt request failed\n"); - goto e_clkdis; - } - - v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops); - state->sd.owner = THIS_MODULE; - snprintf(state->sd.name, sizeof(state->sd.name), "%s.%d", - CSIS_SUBDEV_NAME, state->index); - 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->sd.entity.function = MEDIA_ENT_F_IO_V4L; - state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - ret = media_entity_pads_init(&state->sd.entity, - CSIS_PADS_NUM, state->pads); - if (ret < 0) - goto e_clkdis; - - /* 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); - memcpy(state->events, s5pcsis_events, sizeof(state->events)); - - pm_runtime_enable(dev); - if (!pm_runtime_enabled(dev)) { - ret = s5pcsis_pm_resume(dev, true); - if (ret < 0) - goto e_m_ent; - } - - dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, wclk: %d, freq: %u\n", - state->num_lanes, state->hs_settle, state->wclk_ext, - state->clk_frequency); - return 0; - -e_m_ent: - media_entity_cleanup(&state->sd.entity); -e_clkdis: - clk_disable(state->clock[CSIS_CLK_MUX]); -e_clkput: - s5pcsis_clk_put(state); - return ret; -} - -static int s5pcsis_pm_suspend(struct device *dev, bool runtime) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - 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 = phy_power_off(state->phy); - 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 v4l2_subdev *sd = dev_get_drvdata(dev); - 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 = phy_power_on(state->phy); - 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 -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 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, true); - clk_disable(state->clock[CSIS_CLK_MUX]); - pm_runtime_set_suspended(&pdev->dev); - s5pcsis_clk_put(state); - - 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 const struct csis_drvdata exynos4_csis_drvdata = { - .interrupt_mask = S5PCSIS_INTMSK_EXYNOS4_EN_ALL, -}; - -static const struct csis_drvdata exynos5_csis_drvdata = { - .interrupt_mask = S5PCSIS_INTMSK_EXYNOS5_EN_ALL, -}; - -static const struct of_device_id s5pcsis_of_match[] = { - { - .compatible = "samsung,s5pv210-csis", - .data = &exynos4_csis_drvdata, - }, { - .compatible = "samsung,exynos4210-csis", - .data = &exynos4_csis_drvdata, - }, { - .compatible = "samsung,exynos5250-csis", - .data = &exynos5_csis_drvdata, - }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, s5pcsis_of_match); - -static struct platform_driver s5pcsis_driver = { - .probe = s5pcsis_probe, - .remove = s5pcsis_remove, - .driver = { - .of_match_table = s5pcsis_of_match, - .name = CSIS_DRIVER_NAME, - .pm = &s5pcsis_pm_ops, - }, -}; - -module_platform_driver(s5pcsis_driver); - -MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); -MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/exynos4-is/mipi-csis.h b/drivers/media/platform/exynos4-is/mipi-csis.h deleted file mode 100644 index 193f253c7907..000000000000 --- a/drivers/media/platform/exynos4-is/mipi-csis.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - */ -#ifndef S5P_MIPI_CSIS_H_ -#define S5P_MIPI_CSIS_H_ - -#define CSIS_DRIVER_NAME "s5p-mipi-csis" -#define CSIS_SUBDEV_NAME CSIS_DRIVER_NAME -#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 |