mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
media: staging: drop omap4iss
The omap4 camera driver has seen no progress since forever, and now OMAP4 support has also been dropped from u-boot (1). So it is time to retire this driver. (1): https://lists.denx.de/pipermail/u-boot/2024-July/558846.html Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
a4e3f00e12
commit
95397784be
@ -1,62 +0,0 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
OMAP4 ISS Driver
|
||||
================
|
||||
|
||||
Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
|
||||
Copyright (C) 2012, Texas Instruments
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The OMAP44XX family of chips contains the Imaging SubSystem (a.k.a. ISS),
|
||||
Which contains several components that can be categorized in 3 big groups:
|
||||
|
||||
- Interfaces (2 Interfaces: CSI2-A & CSI2-B/CCP2)
|
||||
- ISP (Image Signal Processor)
|
||||
- SIMCOP (Still Image Coprocessor)
|
||||
|
||||
For more information, please look in [#f1]_ for latest version of:
|
||||
"OMAP4430 Multimedia Device Silicon Revision 2.x"
|
||||
|
||||
As of Revision AB, the ISS is described in detail in section 8.
|
||||
|
||||
This driver is supporting **only** the CSI2-A/B interfaces for now.
|
||||
|
||||
It makes use of the Media Controller framework [#f2]_, and inherited most of the
|
||||
code from OMAP3 ISP driver (found under drivers/media/platform/ti/omap3isp/\*),
|
||||
except that it doesn't need an IOMMU now for ISS buffers memory mapping.
|
||||
|
||||
Supports usage of MMAP buffers only (for now).
|
||||
|
||||
Tested platforms
|
||||
----------------
|
||||
|
||||
- OMAP4430SDP, w/ ES2.1 GP & SEVM4430-CAM-V1-0 (Contains IMX060 & OV5640, in
|
||||
which only the last one is supported, outputting YUV422 frames).
|
||||
|
||||
- TI Blaze MDP, w/ OMAP4430 ES2.2 EMU (Contains 1 IMX060 & 2 OV5650 sensors, in
|
||||
which only the OV5650 are supported, outputting RAW10 frames).
|
||||
|
||||
- PandaBoard, Rev. A2, w/ OMAP4430 ES2.1 GP & OV adapter board, tested with
|
||||
following sensors:
|
||||
* OV5640
|
||||
* OV5650
|
||||
|
||||
- Tested on mainline kernel:
|
||||
|
||||
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=summary
|
||||
|
||||
Tag: v3.3 (commit c16fa4f2ad19908a47c63d8fa436a1178438c7e7)
|
||||
|
||||
File list
|
||||
---------
|
||||
drivers/staging/media/omap4iss/
|
||||
include/linux/platform_data/media/omap4iss.h
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
.. [#f1] http://focus.ti.com/general/docs/wtbu/wtbudocumentcenter.tsp?navigationId=12037&templateId=6123#62
|
||||
.. [#f2] http://lwn.net/Articles/420485/
|
@ -20,7 +20,6 @@ Video4Linux (V4L) driver-specific documentation
|
||||
ivtv
|
||||
mgb4
|
||||
omap3isp
|
||||
omap4_camera
|
||||
philips
|
||||
qcom_camss
|
||||
raspberrypi-pisp-be
|
||||
|
@ -16932,14 +16932,6 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml
|
||||
F: drivers/i2c/busses/i2c-omap.c
|
||||
|
||||
OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS)
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/media/ti,omap3isp.txt
|
||||
F: drivers/media/platform/ti/omap3isp/
|
||||
F: drivers/staging/media/omap4iss/
|
||||
|
||||
OMAP MMC SUPPORT
|
||||
M: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
L: linux-omap@vger.kernel.org
|
||||
|
@ -32,8 +32,6 @@ source "drivers/staging/media/max96712/Kconfig"
|
||||
|
||||
source "drivers/staging/media/meson/vdec/Kconfig"
|
||||
|
||||
source "drivers/staging/media/omap4iss/Kconfig"
|
||||
|
||||
source "drivers/staging/media/rkvdec/Kconfig"
|
||||
|
||||
source "drivers/staging/media/starfive/Kconfig"
|
||||
|
@ -4,7 +4,6 @@ obj-$(CONFIG_INTEL_ATOMISP) += atomisp/
|
||||
obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/
|
||||
obj-$(CONFIG_VIDEO_MAX96712) += max96712/
|
||||
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/
|
||||
obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
|
||||
obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/
|
||||
obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive/
|
||||
obj-$(CONFIG_VIDEO_SUNXI) += sunxi/
|
||||
|
@ -1,12 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
config VIDEO_OMAP4
|
||||
tristate "OMAP 4 Camera support"
|
||||
depends on VIDEO_DEV && I2C
|
||||
depends on ARCH_OMAP4 || COMPILE_TEST
|
||||
select MEDIA_CONTROLLER
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
select MFD_SYSCON
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
help
|
||||
Driver for an OMAP 4 ISS controller.
|
@ -1,9 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for OMAP4 ISS driver
|
||||
#
|
||||
|
||||
omap4-iss-objs += \
|
||||
iss.o iss_csi2.o iss_csiphy.o iss_ipipeif.o iss_ipipe.o iss_resizer.o iss_video.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_OMAP4) += omap4-iss.o
|
@ -1,3 +0,0 @@
|
||||
* Fix FIFO/buffer overflows and underflows
|
||||
* Replace dummy resizer code with a real implementation
|
||||
* Fix checkpatch errors and warnings
|
File diff suppressed because it is too large
Load Diff
@ -1,247 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _OMAP4_ISS_H_
|
||||
#define _OMAP4_ISS_H_
|
||||
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-mc.h>
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <linux/platform_data/media/omap4iss.h>
|
||||
|
||||
#include "iss_regs.h"
|
||||
#include "iss_csiphy.h"
|
||||
#include "iss_csi2.h"
|
||||
#include "iss_ipipeif.h"
|
||||
#include "iss_ipipe.h"
|
||||
#include "iss_resizer.h"
|
||||
|
||||
struct regmap;
|
||||
|
||||
#define to_iss_device(ptr_module) \
|
||||
container_of(ptr_module, struct iss_device, ptr_module)
|
||||
#define to_device(ptr_module) \
|
||||
(to_iss_device(ptr_module)->dev)
|
||||
|
||||
enum iss_mem_resources {
|
||||
OMAP4_ISS_MEM_TOP,
|
||||
OMAP4_ISS_MEM_CSI2_A_REGS1,
|
||||
OMAP4_ISS_MEM_CAMERARX_CORE1,
|
||||
OMAP4_ISS_MEM_CSI2_B_REGS1,
|
||||
OMAP4_ISS_MEM_CAMERARX_CORE2,
|
||||
OMAP4_ISS_MEM_BTE,
|
||||
OMAP4_ISS_MEM_ISP_SYS1,
|
||||
OMAP4_ISS_MEM_ISP_RESIZER,
|
||||
OMAP4_ISS_MEM_ISP_IPIPE,
|
||||
OMAP4_ISS_MEM_ISP_ISIF,
|
||||
OMAP4_ISS_MEM_ISP_IPIPEIF,
|
||||
OMAP4_ISS_MEM_LAST,
|
||||
};
|
||||
|
||||
enum iss_subclk_resource {
|
||||
OMAP4_ISS_SUBCLK_SIMCOP = (1 << 0),
|
||||
OMAP4_ISS_SUBCLK_ISP = (1 << 1),
|
||||
OMAP4_ISS_SUBCLK_CSI2_A = (1 << 2),
|
||||
OMAP4_ISS_SUBCLK_CSI2_B = (1 << 3),
|
||||
OMAP4_ISS_SUBCLK_CCP2 = (1 << 4),
|
||||
};
|
||||
|
||||
enum iss_isp_subclk_resource {
|
||||
OMAP4_ISS_ISP_SUBCLK_BL = (1 << 0),
|
||||
OMAP4_ISS_ISP_SUBCLK_ISIF = (1 << 1),
|
||||
OMAP4_ISS_ISP_SUBCLK_H3A = (1 << 2),
|
||||
OMAP4_ISS_ISP_SUBCLK_RSZ = (1 << 3),
|
||||
OMAP4_ISS_ISP_SUBCLK_IPIPE = (1 << 4),
|
||||
OMAP4_ISS_ISP_SUBCLK_IPIPEIF = (1 << 5),
|
||||
};
|
||||
|
||||
/*
|
||||
* struct iss_reg - Structure for ISS register values.
|
||||
* @reg: 32-bit Register address.
|
||||
* @val: 32-bit Register value.
|
||||
*/
|
||||
struct iss_reg {
|
||||
enum iss_mem_resources mmio_range;
|
||||
u32 reg;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct iss_device - ISS device structure.
|
||||
* @syscon: Regmap for the syscon register space
|
||||
* @crashed: Crashed entities
|
||||
*/
|
||||
struct iss_device {
|
||||
struct v4l2_device v4l2_dev;
|
||||
struct media_device media_dev;
|
||||
struct device *dev;
|
||||
u32 revision;
|
||||
|
||||
/* platform HW resources */
|
||||
struct iss_platform_data *pdata;
|
||||
unsigned int irq_num;
|
||||
|
||||
struct resource *res[OMAP4_ISS_MEM_LAST];
|
||||
void __iomem *regs[OMAP4_ISS_MEM_LAST];
|
||||
struct regmap *syscon;
|
||||
|
||||
u64 raw_dmamask;
|
||||
|
||||
struct mutex iss_mutex; /* For handling ref_count field */
|
||||
struct media_entity_enum crashed;
|
||||
int has_context;
|
||||
int ref_count;
|
||||
|
||||
struct clk *iss_fck;
|
||||
struct clk *iss_ctrlclk;
|
||||
|
||||
/* ISS modules */
|
||||
struct iss_csi2_device csi2a;
|
||||
struct iss_csi2_device csi2b;
|
||||
struct iss_csiphy csiphy1;
|
||||
struct iss_csiphy csiphy2;
|
||||
struct iss_ipipeif_device ipipeif;
|
||||
struct iss_ipipe_device ipipe;
|
||||
struct iss_resizer_device resizer;
|
||||
|
||||
unsigned int subclk_resources;
|
||||
unsigned int isp_subclk_resources;
|
||||
};
|
||||
|
||||
int omap4iss_get_external_info(struct iss_pipeline *pipe,
|
||||
struct media_link *link);
|
||||
|
||||
int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
|
||||
atomic_t *stopping);
|
||||
|
||||
int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait,
|
||||
atomic_t *stopping);
|
||||
|
||||
int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe,
|
||||
enum iss_pipeline_stream_state state);
|
||||
void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe);
|
||||
|
||||
void omap4iss_configure_bridge(struct iss_device *iss,
|
||||
enum ipipeif_input_entity input);
|
||||
|
||||
struct iss_device *omap4iss_get(struct iss_device *iss);
|
||||
void omap4iss_put(struct iss_device *iss);
|
||||
int omap4iss_subclk_enable(struct iss_device *iss,
|
||||
enum iss_subclk_resource res);
|
||||
int omap4iss_subclk_disable(struct iss_device *iss,
|
||||
enum iss_subclk_resource res);
|
||||
void omap4iss_isp_subclk_enable(struct iss_device *iss,
|
||||
enum iss_isp_subclk_resource res);
|
||||
void omap4iss_isp_subclk_disable(struct iss_device *iss,
|
||||
enum iss_isp_subclk_resource res);
|
||||
|
||||
int omap4iss_register_entities(struct platform_device *pdev,
|
||||
struct v4l2_device *v4l2_dev);
|
||||
void omap4iss_unregister_entities(struct platform_device *pdev);
|
||||
|
||||
/*
|
||||
* iss_reg_read - Read the value of an OMAP4 ISS register
|
||||
* @iss: the ISS device
|
||||
* @res: memory resource in which the register is located
|
||||
* @offset: register offset in the memory resource
|
||||
*
|
||||
* Return the register value.
|
||||
*/
|
||||
static inline
|
||||
u32 iss_reg_read(struct iss_device *iss, enum iss_mem_resources res,
|
||||
u32 offset)
|
||||
{
|
||||
return readl(iss->regs[res] + offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* iss_reg_write - Write a value to an OMAP4 ISS register
|
||||
* @iss: the ISS device
|
||||
* @res: memory resource in which the register is located
|
||||
* @offset: register offset in the memory resource
|
||||
* @value: value to be written
|
||||
*/
|
||||
static inline
|
||||
void iss_reg_write(struct iss_device *iss, enum iss_mem_resources res,
|
||||
u32 offset, u32 value)
|
||||
{
|
||||
writel(value, iss->regs[res] + offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* iss_reg_clr - Clear bits in an OMAP4 ISS register
|
||||
* @iss: the ISS device
|
||||
* @res: memory resource in which the register is located
|
||||
* @offset: register offset in the memory resource
|
||||
* @clr: bit mask to be cleared
|
||||
*/
|
||||
static inline
|
||||
void iss_reg_clr(struct iss_device *iss, enum iss_mem_resources res,
|
||||
u32 offset, u32 clr)
|
||||
{
|
||||
u32 v = iss_reg_read(iss, res, offset);
|
||||
|
||||
iss_reg_write(iss, res, offset, v & ~clr);
|
||||
}
|
||||
|
||||
/*
|
||||
* iss_reg_set - Set bits in an OMAP4 ISS register
|
||||
* @iss: the ISS device
|
||||
* @res: memory resource in which the register is located
|
||||
* @offset: register offset in the memory resource
|
||||
* @set: bit mask to be set
|
||||
*/
|
||||
static inline
|
||||
void iss_reg_set(struct iss_device *iss, enum iss_mem_resources res,
|
||||
u32 offset, u32 set)
|
||||
{
|
||||
u32 v = iss_reg_read(iss, res, offset);
|
||||
|
||||
iss_reg_write(iss, res, offset, v | set);
|
||||
}
|
||||
|
||||
/*
|
||||
* iss_reg_update - Clear and set bits in an OMAP4 ISS register
|
||||
* @iss: the ISS device
|
||||
* @res: memory resource in which the register is located
|
||||
* @offset: register offset in the memory resource
|
||||
* @clr: bit mask to be cleared
|
||||
* @set: bit mask to be set
|
||||
*
|
||||
* Clear the clr mask first and then set the set mask.
|
||||
*/
|
||||
static inline
|
||||
void iss_reg_update(struct iss_device *iss, enum iss_mem_resources res,
|
||||
u32 offset, u32 clr, u32 set)
|
||||
{
|
||||
u32 v = iss_reg_read(iss, res, offset);
|
||||
|
||||
iss_reg_write(iss, res, offset, (v & ~clr) | set);
|
||||
}
|
||||
|
||||
#define iss_poll_condition_timeout(cond, timeout, min_ival, max_ival) \
|
||||
({ \
|
||||
unsigned long __timeout = jiffies + usecs_to_jiffies(timeout); \
|
||||
unsigned int __min_ival = (min_ival); \
|
||||
unsigned int __max_ival = (max_ival); \
|
||||
bool __cond; \
|
||||
while (!(__cond = (cond))) { \
|
||||
if (time_after(jiffies, __timeout)) \
|
||||
break; \
|
||||
usleep_range(__min_ival, __max_ival); \
|
||||
} \
|
||||
!__cond; \
|
||||
})
|
||||
|
||||
#endif /* _OMAP4_ISS_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -1,155 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - CSI2 module
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef OMAP4_ISS_CSI2_H
|
||||
#define OMAP4_ISS_CSI2_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include "iss_video.h"
|
||||
|
||||
struct iss_csiphy;
|
||||
|
||||
/* This is not an exhaustive list */
|
||||
enum iss_csi2_pix_formats {
|
||||
CSI2_PIX_FMT_OTHERS = 0,
|
||||
CSI2_PIX_FMT_YUV422_8BIT = 0x1e,
|
||||
CSI2_PIX_FMT_YUV422_8BIT_VP = 0x9e,
|
||||
CSI2_PIX_FMT_YUV422_8BIT_VP16 = 0xde,
|
||||
CSI2_PIX_FMT_RAW10_EXP16 = 0xab,
|
||||
CSI2_PIX_FMT_RAW10_EXP16_VP = 0x12f,
|
||||
CSI2_PIX_FMT_RAW8 = 0x2a,
|
||||
CSI2_PIX_FMT_RAW8_DPCM10_EXP16 = 0x2aa,
|
||||
CSI2_PIX_FMT_RAW8_DPCM10_VP = 0x32a,
|
||||
CSI2_PIX_FMT_RAW8_VP = 0x12a,
|
||||
CSI2_USERDEF_8BIT_DATA1_DPCM10_VP = 0x340,
|
||||
CSI2_USERDEF_8BIT_DATA1_DPCM10 = 0x2c0,
|
||||
CSI2_USERDEF_8BIT_DATA1 = 0x40,
|
||||
};
|
||||
|
||||
enum iss_csi2_irqevents {
|
||||
OCP_ERR_IRQ = 0x4000,
|
||||
SHORT_PACKET_IRQ = 0x2000,
|
||||
ECC_CORRECTION_IRQ = 0x1000,
|
||||
ECC_NO_CORRECTION_IRQ = 0x800,
|
||||
COMPLEXIO2_ERR_IRQ = 0x400,
|
||||
COMPLEXIO1_ERR_IRQ = 0x200,
|
||||
FIFO_OVF_IRQ = 0x100,
|
||||
CONTEXT7 = 0x80,
|
||||
CONTEXT6 = 0x40,
|
||||
CONTEXT5 = 0x20,
|
||||
CONTEXT4 = 0x10,
|
||||
CONTEXT3 = 0x8,
|
||||
CONTEXT2 = 0x4,
|
||||
CONTEXT1 = 0x2,
|
||||
CONTEXT0 = 0x1,
|
||||
};
|
||||
|
||||
enum iss_csi2_ctx_irqevents {
|
||||
CTX_ECC_CORRECTION = 0x100,
|
||||
CTX_LINE_NUMBER = 0x80,
|
||||
CTX_FRAME_NUMBER = 0x40,
|
||||
CTX_CS = 0x20,
|
||||
CTX_LE = 0x8,
|
||||
CTX_LS = 0x4,
|
||||
CTX_FE = 0x2,
|
||||
CTX_FS = 0x1,
|
||||
};
|
||||
|
||||
enum iss_csi2_frame_mode {
|
||||
ISS_CSI2_FRAME_IMMEDIATE,
|
||||
ISS_CSI2_FRAME_AFTERFEC,
|
||||
};
|
||||
|
||||
#define ISS_CSI2_MAX_CTX_NUM 7
|
||||
|
||||
struct iss_csi2_ctx_cfg {
|
||||
u8 ctxnum; /* context number 0 - 7 */
|
||||
u8 dpcm_decompress;
|
||||
|
||||
/* Fields in CSI2_CTx_CTRL2 - locked by CSI2_CTx_CTRL1.CTX_EN */
|
||||
u8 virtual_id;
|
||||
u16 format_id; /* as in CSI2_CTx_CTRL2[9:0] */
|
||||
u8 dpcm_predictor; /* 1: simple, 0: advanced */
|
||||
u16 frame;
|
||||
|
||||
/* Fields in CSI2_CTx_CTRL1/3 - Shadowed */
|
||||
u16 alpha;
|
||||
u16 data_offset;
|
||||
u32 ping_addr;
|
||||
u32 pong_addr;
|
||||
u8 eof_enabled;
|
||||
u8 eol_enabled;
|
||||
u8 checksum_enabled;
|
||||
u8 enabled;
|
||||
};
|
||||
|
||||
struct iss_csi2_timing_cfg {
|
||||
u8 ionum; /* IO1 or IO2 as in CSI2_TIMING */
|
||||
unsigned force_rx_mode:1;
|
||||
unsigned stop_state_16x:1;
|
||||
unsigned stop_state_4x:1;
|
||||
u16 stop_state_counter;
|
||||
};
|
||||
|
||||
struct iss_csi2_ctrl_cfg {
|
||||
bool vp_clk_enable;
|
||||
bool vp_only_enable;
|
||||
u8 vp_out_ctrl;
|
||||
enum iss_csi2_frame_mode frame_mode;
|
||||
bool ecc_enable;
|
||||
bool if_enable;
|
||||
};
|
||||
|
||||
#define CSI2_PAD_SINK 0
|
||||
#define CSI2_PAD_SOURCE 1
|
||||
#define CSI2_PADS_NUM 2
|
||||
|
||||
#define CSI2_OUTPUT_IPIPEIF BIT(0)
|
||||
#define CSI2_OUTPUT_MEMORY BIT(1)
|
||||
|
||||
struct iss_csi2_device {
|
||||
struct v4l2_subdev subdev;
|
||||
struct media_pad pads[CSI2_PADS_NUM];
|
||||
struct v4l2_mbus_framefmt formats[CSI2_PADS_NUM];
|
||||
|
||||
struct iss_video video_out;
|
||||
struct iss_device *iss;
|
||||
|
||||
u8 available; /* Is the IP present on the silicon? */
|
||||
|
||||
/* memory resources, as defined in enum iss_mem_resources */
|
||||
unsigned int regs1;
|
||||
unsigned int regs2;
|
||||
/* ISP subclock, as defined in enum iss_isp_subclk_resource */
|
||||
unsigned int subclk;
|
||||
|
||||
u32 output; /* output to IPIPEIF, memory or both? */
|
||||
bool dpcm_decompress;
|
||||
unsigned int frame_skip;
|
||||
|
||||
struct iss_csiphy *phy;
|
||||
struct iss_csi2_ctx_cfg contexts[ISS_CSI2_MAX_CTX_NUM + 1];
|
||||
struct iss_csi2_timing_cfg timing[2];
|
||||
struct iss_csi2_ctrl_cfg ctrl;
|
||||
enum iss_pipeline_stream_state state;
|
||||
wait_queue_head_t wait;
|
||||
atomic_t stopping;
|
||||
};
|
||||
|
||||
void omap4iss_csi2_isr(struct iss_csi2_device *csi2);
|
||||
int omap4iss_csi2_reset(struct iss_csi2_device *csi2);
|
||||
int omap4iss_csi2_init(struct iss_device *iss);
|
||||
int omap4iss_csi2_create_links(struct iss_device *iss);
|
||||
void omap4iss_csi2_cleanup(struct iss_device *iss);
|
||||
void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2);
|
||||
int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2,
|
||||
struct v4l2_device *vdev);
|
||||
#endif /* OMAP4_ISS_CSI2_H */
|
@ -1,277 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - CSI PHY module
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "../../../../arch/arm/mach-omap2/control.h"
|
||||
|
||||
#include "iss.h"
|
||||
#include "iss_regs.h"
|
||||
#include "iss_csiphy.h"
|
||||
|
||||
/*
|
||||
* csiphy_lanes_config - Configuration of CSIPHY lanes.
|
||||
*
|
||||
* Updates HW configuration.
|
||||
* Called with phy->mutex taken.
|
||||
*/
|
||||
static void csiphy_lanes_config(struct iss_csiphy *phy)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 reg;
|
||||
|
||||
reg = iss_reg_read(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG);
|
||||
|
||||
for (i = 0; i < phy->max_data_lanes; i++) {
|
||||
reg &= ~(CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) |
|
||||
CSI2_COMPLEXIO_CFG_DATA_POSITION_MASK(i + 1));
|
||||
reg |= (phy->lanes.data[i].pol ?
|
||||
CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) : 0);
|
||||
reg |= (phy->lanes.data[i].pos <<
|
||||
CSI2_COMPLEXIO_CFG_DATA_POSITION_SHIFT(i + 1));
|
||||
}
|
||||
|
||||
reg &= ~(CSI2_COMPLEXIO_CFG_CLOCK_POL |
|
||||
CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK);
|
||||
reg |= phy->lanes.clk.pol ? CSI2_COMPLEXIO_CFG_CLOCK_POL : 0;
|
||||
reg |= phy->lanes.clk.pos << CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT;
|
||||
|
||||
iss_reg_write(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* csiphy_set_power
|
||||
* @power: Power state to be set.
|
||||
*
|
||||
* Returns 0 if successful, or -EBUSY if the retry count is exceeded.
|
||||
*/
|
||||
static int csiphy_set_power(struct iss_csiphy *phy, u32 power)
|
||||
{
|
||||
u32 reg;
|
||||
u8 retry_count;
|
||||
|
||||
iss_reg_update(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG,
|
||||
CSI2_COMPLEXIO_CFG_PWD_CMD_MASK,
|
||||
power | CSI2_COMPLEXIO_CFG_PWR_AUTO);
|
||||
|
||||
retry_count = 0;
|
||||
do {
|
||||
udelay(1);
|
||||
reg = iss_reg_read(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG)
|
||||
& CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK;
|
||||
|
||||
if (reg != power >> 2)
|
||||
retry_count++;
|
||||
|
||||
} while ((reg != power >> 2) && (retry_count < 250));
|
||||
|
||||
if (retry_count == 250) {
|
||||
dev_err(phy->iss->dev, "CSI2 CIO set power failed!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* csiphy_dphy_config - Configure CSI2 D-PHY parameters.
|
||||
*
|
||||
* Called with phy->mutex taken.
|
||||
*/
|
||||
static void csiphy_dphy_config(struct iss_csiphy *phy)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/* Set up REGISTER0 */
|
||||
reg = phy->dphy.ths_term << REGISTER0_THS_TERM_SHIFT;
|
||||
reg |= phy->dphy.ths_settle << REGISTER0_THS_SETTLE_SHIFT;
|
||||
|
||||
iss_reg_write(phy->iss, phy->phy_regs, REGISTER0, reg);
|
||||
|
||||
/* Set up REGISTER1 */
|
||||
reg = phy->dphy.tclk_term << REGISTER1_TCLK_TERM_SHIFT;
|
||||
reg |= phy->dphy.tclk_miss << REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT;
|
||||
reg |= phy->dphy.tclk_settle << REGISTER1_TCLK_SETTLE_SHIFT;
|
||||
reg |= 0xb8 << REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT;
|
||||
|
||||
iss_reg_write(phy->iss, phy->phy_regs, REGISTER1, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* TCLK values are OK at their reset values
|
||||
*/
|
||||
#define TCLK_TERM 0
|
||||
#define TCLK_MISS 1
|
||||
#define TCLK_SETTLE 14
|
||||
|
||||
int omap4iss_csiphy_config(struct iss_device *iss,
|
||||
struct v4l2_subdev *csi2_subdev)
|
||||
{
|
||||
struct iss_csi2_device *csi2 = v4l2_get_subdevdata(csi2_subdev);
|
||||
struct iss_pipeline *pipe = to_iss_pipeline(&csi2_subdev->entity);
|
||||
struct iss_v4l2_subdevs_group *subdevs = pipe->external->host_priv;
|
||||
struct iss_csiphy_dphy_cfg csi2phy;
|
||||
int csi2_ddrclk_khz;
|
||||
struct iss_csiphy_lanes_cfg *lanes;
|
||||
unsigned int used_lanes = 0;
|
||||
u32 cam_rx_ctrl;
|
||||
unsigned int i;
|
||||
|
||||
lanes = &subdevs->bus.csi2.lanecfg;
|
||||
|
||||
/*
|
||||
* SCM.CONTROL_CAMERA_RX
|
||||
* - bit [31] : CSIPHY2 lane 2 enable (4460+ only)
|
||||
* - bit [30:29] : CSIPHY2 per-lane enable (1 to 0)
|
||||
* - bit [28:24] : CSIPHY1 per-lane enable (4 to 0)
|
||||
* - bit [21] : CSIPHY2 CTRLCLK enable
|
||||
* - bit [20:19] : CSIPHY2 config: 00 d-phy, 01/10 ccp2
|
||||
* - bit [18] : CSIPHY1 CTRLCLK enable
|
||||
* - bit [17:16] : CSIPHY1 config: 00 d-phy, 01/10 ccp2
|
||||
*/
|
||||
/*
|
||||
* TODO: When implementing DT support specify the CONTROL_CAMERA_RX
|
||||
* register offset in the syscon property instead of hardcoding it.
|
||||
*/
|
||||
regmap_read(iss->syscon, 0x68, &cam_rx_ctrl);
|
||||
|
||||
if (subdevs->interface == ISS_INTERFACE_CSI2A_PHY1) {
|
||||
cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI21_LANEENABLE_MASK |
|
||||
OMAP4_CAMERARX_CSI21_CAMMODE_MASK);
|
||||
/* NOTE: Leave CSIPHY1 config to 0x0: D-PHY mode */
|
||||
/* Enable all lanes for now */
|
||||
cam_rx_ctrl |=
|
||||
0x1f << OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT;
|
||||
/* Enable CTRLCLK */
|
||||
cam_rx_ctrl |= OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK;
|
||||
}
|
||||
|
||||
if (subdevs->interface == ISS_INTERFACE_CSI2B_PHY2) {
|
||||
cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI22_LANEENABLE_MASK |
|
||||
OMAP4_CAMERARX_CSI22_CAMMODE_MASK);
|
||||
/* NOTE: Leave CSIPHY2 config to 0x0: D-PHY mode */
|
||||
/* Enable all lanes for now */
|
||||
cam_rx_ctrl |=
|
||||
0x3 << OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT;
|
||||
/* Enable CTRLCLK */
|
||||
cam_rx_ctrl |= OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK;
|
||||
}
|
||||
|
||||
regmap_write(iss->syscon, 0x68, cam_rx_ctrl);
|
||||
|
||||
/* Reset used lane count */
|
||||
csi2->phy->used_data_lanes = 0;
|
||||
|
||||
/* Clock and data lanes verification */
|
||||
for (i = 0; i < csi2->phy->max_data_lanes; i++) {
|
||||
if (lanes->data[i].pos == 0)
|
||||
continue;
|
||||
|
||||
if (lanes->data[i].pol > 1 ||
|
||||
lanes->data[i].pos > (csi2->phy->max_data_lanes + 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (used_lanes & (1 << lanes->data[i].pos))
|
||||
return -EINVAL;
|
||||
|
||||
used_lanes |= 1 << lanes->data[i].pos;
|
||||
csi2->phy->used_data_lanes++;
|
||||
}
|
||||
|
||||
if (lanes->clk.pol > 1 ||
|
||||
lanes->clk.pos > (csi2->phy->max_data_lanes + 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos))
|
||||
return -EINVAL;
|
||||
|
||||
csi2_ddrclk_khz = pipe->external_rate / 1000
|
||||
/ (2 * csi2->phy->used_data_lanes)
|
||||
* pipe->external_bpp;
|
||||
|
||||
/*
|
||||
* THS_TERM: Programmed value = ceil(12.5 ns/DDRClk period) - 1.
|
||||
* THS_SETTLE: Programmed value = ceil(90 ns/DDRClk period) + 3.
|
||||
*/
|
||||
csi2phy.ths_term = DIV_ROUND_UP(25 * csi2_ddrclk_khz, 2000000) - 1;
|
||||
csi2phy.ths_settle = DIV_ROUND_UP(90 * csi2_ddrclk_khz, 1000000) + 3;
|
||||
csi2phy.tclk_term = TCLK_TERM;
|
||||
csi2phy.tclk_miss = TCLK_MISS;
|
||||
csi2phy.tclk_settle = TCLK_SETTLE;
|
||||
|
||||
mutex_lock(&csi2->phy->mutex);
|
||||
csi2->phy->dphy = csi2phy;
|
||||
csi2->phy->lanes = *lanes;
|
||||
mutex_unlock(&csi2->phy->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omap4iss_csiphy_acquire(struct iss_csiphy *phy)
|
||||
{
|
||||
int rval;
|
||||
|
||||
mutex_lock(&phy->mutex);
|
||||
|
||||
rval = omap4iss_csi2_reset(phy->csi2);
|
||||
if (rval)
|
||||
goto done;
|
||||
|
||||
csiphy_dphy_config(phy);
|
||||
csiphy_lanes_config(phy);
|
||||
|
||||
rval = csiphy_set_power(phy, CSI2_COMPLEXIO_CFG_PWD_CMD_ON);
|
||||
if (rval)
|
||||
goto done;
|
||||
|
||||
phy->phy_in_use = 1;
|
||||
|
||||
done:
|
||||
mutex_unlock(&phy->mutex);
|
||||
return rval;
|
||||
}
|
||||
|
||||
void omap4iss_csiphy_release(struct iss_csiphy *phy)
|
||||
{
|
||||
mutex_lock(&phy->mutex);
|
||||
if (phy->phy_in_use) {
|
||||
csiphy_set_power(phy, CSI2_COMPLEXIO_CFG_PWD_CMD_OFF);
|
||||
phy->phy_in_use = 0;
|
||||
}
|
||||
mutex_unlock(&phy->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* omap4iss_csiphy_init - Initialize the CSI PHY frontends
|
||||
*/
|
||||
int omap4iss_csiphy_init(struct iss_device *iss)
|
||||
{
|
||||
struct iss_csiphy *phy1 = &iss->csiphy1;
|
||||
struct iss_csiphy *phy2 = &iss->csiphy2;
|
||||
|
||||
phy1->iss = iss;
|
||||
phy1->csi2 = &iss->csi2a;
|
||||
phy1->max_data_lanes = ISS_CSIPHY1_NUM_DATA_LANES;
|
||||
phy1->used_data_lanes = 0;
|
||||
phy1->cfg_regs = OMAP4_ISS_MEM_CSI2_A_REGS1;
|
||||
phy1->phy_regs = OMAP4_ISS_MEM_CAMERARX_CORE1;
|
||||
mutex_init(&phy1->mutex);
|
||||
|
||||
phy2->iss = iss;
|
||||
phy2->csi2 = &iss->csi2b;
|
||||
phy2->max_data_lanes = ISS_CSIPHY2_NUM_DATA_LANES;
|
||||
phy2->used_data_lanes = 0;
|
||||
phy2->cfg_regs = OMAP4_ISS_MEM_CSI2_B_REGS1;
|
||||
phy2->phy_regs = OMAP4_ISS_MEM_CAMERARX_CORE2;
|
||||
mutex_init(&phy2->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - CSI PHY module
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef OMAP4_ISS_CSI_PHY_H
|
||||
#define OMAP4_ISS_CSI_PHY_H
|
||||
|
||||
#include <linux/platform_data/media/omap4iss.h>
|
||||
|
||||
struct iss_csi2_device;
|
||||
|
||||
struct iss_csiphy_dphy_cfg {
|
||||
u8 ths_term;
|
||||
u8 ths_settle;
|
||||
u8 tclk_term;
|
||||
unsigned tclk_miss:1;
|
||||
u8 tclk_settle;
|
||||
};
|
||||
|
||||
struct iss_csiphy {
|
||||
struct iss_device *iss;
|
||||
struct mutex mutex; /* serialize csiphy configuration */
|
||||
u8 phy_in_use;
|
||||
struct iss_csi2_device *csi2;
|
||||
|
||||
/* memory resources, as defined in enum iss_mem_resources */
|
||||
unsigned int cfg_regs;
|
||||
unsigned int phy_regs;
|
||||
|
||||
u8 max_data_lanes; /* number of CSI2 Data Lanes supported */
|
||||
u8 used_data_lanes; /* number of CSI2 Data Lanes used */
|
||||
struct iss_csiphy_lanes_cfg lanes;
|
||||
struct iss_csiphy_dphy_cfg dphy;
|
||||
};
|
||||
|
||||
int omap4iss_csiphy_config(struct iss_device *iss,
|
||||
struct v4l2_subdev *csi2_subdev);
|
||||
int omap4iss_csiphy_acquire(struct iss_csiphy *phy);
|
||||
void omap4iss_csiphy_release(struct iss_csiphy *phy);
|
||||
int omap4iss_csiphy_init(struct iss_device *iss);
|
||||
|
||||
#endif /* OMAP4_ISS_CSI_PHY_H */
|
@ -1,579 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - ISP IPIPE module
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "iss.h"
|
||||
#include "iss_regs.h"
|
||||
#include "iss_ipipe.h"
|
||||
|
||||
static struct v4l2_mbus_framefmt *
|
||||
__ipipe_get_format(struct iss_ipipe_device *ipipe,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
unsigned int pad,
|
||||
enum v4l2_subdev_format_whence which);
|
||||
|
||||
static const unsigned int ipipe_fmts[] = {
|
||||
MEDIA_BUS_FMT_SGRBG10_1X10,
|
||||
MEDIA_BUS_FMT_SRGGB10_1X10,
|
||||
MEDIA_BUS_FMT_SBGGR10_1X10,
|
||||
MEDIA_BUS_FMT_SGBRG10_1X10,
|
||||
};
|
||||
|
||||
/*
|
||||
* ipipe_print_status - Print current IPIPE Module register values.
|
||||
* @ipipe: Pointer to ISS ISP IPIPE device.
|
||||
*
|
||||
* Also prints other debug information stored in the IPIPE module.
|
||||
*/
|
||||
#define IPIPE_PRINT_REGISTER(iss, name)\
|
||||
dev_dbg(iss->dev, "###IPIPE " #name "=0x%08x\n", \
|
||||
iss_reg_read(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_##name))
|
||||
|
||||
static void ipipe_print_status(struct iss_ipipe_device *ipipe)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(ipipe);
|
||||
|
||||
dev_dbg(iss->dev, "-------------IPIPE Register dump-------------\n");
|
||||
|
||||
IPIPE_PRINT_REGISTER(iss, SRC_EN);
|
||||
IPIPE_PRINT_REGISTER(iss, SRC_MODE);
|
||||
IPIPE_PRINT_REGISTER(iss, SRC_FMT);
|
||||
IPIPE_PRINT_REGISTER(iss, SRC_COL);
|
||||
IPIPE_PRINT_REGISTER(iss, SRC_VPS);
|
||||
IPIPE_PRINT_REGISTER(iss, SRC_VSZ);
|
||||
IPIPE_PRINT_REGISTER(iss, SRC_HPS);
|
||||
IPIPE_PRINT_REGISTER(iss, SRC_HSZ);
|
||||
IPIPE_PRINT_REGISTER(iss, GCK_MMR);
|
||||
IPIPE_PRINT_REGISTER(iss, YUV_PHS);
|
||||
|
||||
dev_dbg(iss->dev, "-----------------------------------------------\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipe_enable - Enable/Disable IPIPE.
|
||||
* @enable: enable flag
|
||||
*
|
||||
*/
|
||||
static void ipipe_enable(struct iss_ipipe_device *ipipe, u8 enable)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(ipipe);
|
||||
|
||||
iss_reg_update(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_EN,
|
||||
IPIPE_SRC_EN_EN, enable ? IPIPE_SRC_EN_EN : 0);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Format- and pipeline-related configuration helpers
|
||||
*/
|
||||
|
||||
static void ipipe_configure(struct iss_ipipe_device *ipipe)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(ipipe);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
|
||||
/* IPIPE_PAD_SINK */
|
||||
format = &ipipe->formats[IPIPE_PAD_SINK];
|
||||
|
||||
/* NOTE: Currently just supporting pipeline IN: RGB, OUT: YUV422 */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_FMT,
|
||||
IPIPE_SRC_FMT_RAW2YUV);
|
||||
|
||||
/* Enable YUV444 -> YUV422 conversion */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_YUV_PHS,
|
||||
IPIPE_YUV_PHS_LPF);
|
||||
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_VPS, 0);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_HPS, 0);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_VSZ,
|
||||
(format->height - 2) & IPIPE_SRC_VSZ_MASK);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_HSZ,
|
||||
(format->width - 1) & IPIPE_SRC_HSZ_MASK);
|
||||
|
||||
/* Ignore ipipeif_wrt signal, and operate on-the-fly. */
|
||||
iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_MODE,
|
||||
IPIPE_SRC_MODE_WRT | IPIPE_SRC_MODE_OST);
|
||||
|
||||
/* HACK: Values tuned for Ducati SW (OV) */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_COL,
|
||||
IPIPE_SRC_COL_EE_B | IPIPE_SRC_COL_EO_GB |
|
||||
IPIPE_SRC_COL_OE_GR | IPIPE_SRC_COL_OO_R);
|
||||
|
||||
/* IPIPE_PAD_SOURCE_VP */
|
||||
format = &ipipe->formats[IPIPE_PAD_SOURCE_VP];
|
||||
/* Do nothing? */
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* V4L2 subdev operations
|
||||
*/
|
||||
|
||||
/*
|
||||
* ipipe_set_stream - Enable/Disable streaming on the IPIPE module
|
||||
* @sd: ISP IPIPE V4L2 subdevice
|
||||
* @enable: Enable/disable stream
|
||||
*/
|
||||
static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
|
||||
struct iss_device *iss = to_iss_device(ipipe);
|
||||
int ret = 0;
|
||||
|
||||
if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED) {
|
||||
if (enable == ISS_PIPELINE_STREAM_STOPPED)
|
||||
return 0;
|
||||
|
||||
omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE);
|
||||
|
||||
/* Enable clk_arm_g0 */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_GCK_MMR,
|
||||
IPIPE_GCK_MMR_REG);
|
||||
|
||||
/* Enable clk_pix_g[3:0] */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_GCK_PIX,
|
||||
IPIPE_GCK_PIX_G3 | IPIPE_GCK_PIX_G2 |
|
||||
IPIPE_GCK_PIX_G1 | IPIPE_GCK_PIX_G0);
|
||||
}
|
||||
|
||||
switch (enable) {
|
||||
case ISS_PIPELINE_STREAM_CONTINUOUS:
|
||||
|
||||
ipipe_configure(ipipe);
|
||||
ipipe_print_status(ipipe);
|
||||
|
||||
atomic_set(&ipipe->stopping, 0);
|
||||
ipipe_enable(ipipe, 1);
|
||||
break;
|
||||
|
||||
case ISS_PIPELINE_STREAM_STOPPED:
|
||||
if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED)
|
||||
return 0;
|
||||
if (omap4iss_module_sync_idle(&sd->entity, &ipipe->wait,
|
||||
&ipipe->stopping))
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
ipipe_enable(ipipe, 0);
|
||||
omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE);
|
||||
break;
|
||||
}
|
||||
|
||||
ipipe->state = enable;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct v4l2_mbus_framefmt *
|
||||
__ipipe_get_format(struct iss_ipipe_device *ipipe,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
unsigned int pad,
|
||||
enum v4l2_subdev_format_whence which)
|
||||
{
|
||||
if (which == V4L2_SUBDEV_FORMAT_TRY)
|
||||
return v4l2_subdev_state_get_format(sd_state, pad);
|
||||
|
||||
return &ipipe->formats[pad];
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipe_try_format - Try video format on a pad
|
||||
* @ipipe: ISS IPIPE device
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @pad: Pad number
|
||||
* @fmt: Format
|
||||
*/
|
||||
static void
|
||||
ipipe_try_format(struct iss_ipipe_device *ipipe,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
unsigned int pad,
|
||||
struct v4l2_mbus_framefmt *fmt,
|
||||
enum v4l2_subdev_format_whence which)
|
||||
{
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
unsigned int width = fmt->width;
|
||||
unsigned int height = fmt->height;
|
||||
unsigned int i;
|
||||
|
||||
switch (pad) {
|
||||
case IPIPE_PAD_SINK:
|
||||
for (i = 0; i < ARRAY_SIZE(ipipe_fmts); i++) {
|
||||
if (fmt->code == ipipe_fmts[i])
|
||||
break;
|
||||
}
|
||||
|
||||
/* If not found, use SGRBG10 as default */
|
||||
if (i >= ARRAY_SIZE(ipipe_fmts))
|
||||
fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
|
||||
|
||||
/* Clamp the input size. */
|
||||
fmt->width = clamp_t(u32, width, 1, 8192);
|
||||
fmt->height = clamp_t(u32, height, 1, 8192);
|
||||
fmt->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
break;
|
||||
|
||||
case IPIPE_PAD_SOURCE_VP:
|
||||
format = __ipipe_get_format(ipipe, sd_state, IPIPE_PAD_SINK,
|
||||
which);
|
||||
memcpy(fmt, format, sizeof(*fmt));
|
||||
|
||||
fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||
fmt->width = clamp_t(u32, width, 32, fmt->width);
|
||||
fmt->height = clamp_t(u32, height, 32, fmt->height);
|
||||
fmt->colorspace = V4L2_COLORSPACE_JPEG;
|
||||
break;
|
||||
}
|
||||
|
||||
fmt->field = V4L2_FIELD_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipe_enum_mbus_code - Handle pixel format enumeration
|
||||
* @sd : pointer to v4l2 subdev structure
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @code : pointer to v4l2_subdev_mbus_code_enum structure
|
||||
* return -EINVAL or zero on success
|
||||
*/
|
||||
static int ipipe_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_mbus_code_enum *code)
|
||||
{
|
||||
switch (code->pad) {
|
||||
case IPIPE_PAD_SINK:
|
||||
if (code->index >= ARRAY_SIZE(ipipe_fmts))
|
||||
return -EINVAL;
|
||||
|
||||
code->code = ipipe_fmts[code->index];
|
||||
break;
|
||||
|
||||
case IPIPE_PAD_SOURCE_VP:
|
||||
/* FIXME: Forced format conversion inside IPIPE ? */
|
||||
if (code->index != 0)
|
||||
return -EINVAL;
|
||||
|
||||
code->code = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_frame_size_enum *fse)
|
||||
{
|
||||
struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt format;
|
||||
|
||||
if (fse->index != 0)
|
||||
return -EINVAL;
|
||||
|
||||
format.code = fse->code;
|
||||
format.width = 1;
|
||||
format.height = 1;
|
||||
ipipe_try_format(ipipe, sd_state, fse->pad, &format, fse->which);
|
||||
fse->min_width = format.width;
|
||||
fse->min_height = format.height;
|
||||
|
||||
if (format.code != fse->code)
|
||||
return -EINVAL;
|
||||
|
||||
format.code = fse->code;
|
||||
format.width = -1;
|
||||
format.height = -1;
|
||||
ipipe_try_format(ipipe, sd_state, fse->pad, &format, fse->which);
|
||||
fse->max_width = format.width;
|
||||
fse->max_height = format.height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipe_get_format - Retrieve the video format on a pad
|
||||
* @sd : ISP IPIPE V4L2 subdevice
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @fmt: Format
|
||||
*
|
||||
* Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
|
||||
* to the format type.
|
||||
*/
|
||||
static int ipipe_get_format(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_format *fmt)
|
||||
{
|
||||
struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
|
||||
format = __ipipe_get_format(ipipe, sd_state, fmt->pad, fmt->which);
|
||||
if (!format)
|
||||
return -EINVAL;
|
||||
|
||||
fmt->format = *format;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipe_set_format - Set the video format on a pad
|
||||
* @sd : ISP IPIPE V4L2 subdevice
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @fmt: Format
|
||||
*
|
||||
* Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
|
||||
* to the format type.
|
||||
*/
|
||||
static int ipipe_set_format(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_format *fmt)
|
||||
{
|
||||
struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
|
||||
format = __ipipe_get_format(ipipe, sd_state, fmt->pad, fmt->which);
|
||||
if (!format)
|
||||
return -EINVAL;
|
||||
|
||||
ipipe_try_format(ipipe, sd_state, fmt->pad, &fmt->format, fmt->which);
|
||||
*format = fmt->format;
|
||||
|
||||
/* Propagate the format from sink to source */
|
||||
if (fmt->pad == IPIPE_PAD_SINK) {
|
||||
format = __ipipe_get_format(ipipe, sd_state,
|
||||
IPIPE_PAD_SOURCE_VP,
|
||||
fmt->which);
|
||||
*format = fmt->format;
|
||||
ipipe_try_format(ipipe, sd_state, IPIPE_PAD_SOURCE_VP, format,
|
||||
fmt->which);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipipe_link_validate(struct v4l2_subdev *sd, struct media_link *link,
|
||||
struct v4l2_subdev_format *source_fmt,
|
||||
struct v4l2_subdev_format *sink_fmt)
|
||||
{
|
||||
/* Check if the two ends match */
|
||||
if (source_fmt->format.width != sink_fmt->format.width ||
|
||||
source_fmt->format.height != sink_fmt->format.height)
|
||||
return -EPIPE;
|
||||
|
||||
if (source_fmt->format.code != sink_fmt->format.code)
|
||||
return -EPIPE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipe_init_formats - Initialize formats on all pads
|
||||
* @sd: ISP IPIPE V4L2 subdevice
|
||||
* @fh: V4L2 subdev file handle
|
||||
*
|
||||
* Initialize all pad formats with default values. If fh is not NULL, try
|
||||
* formats are initialized on the file handle. Otherwise active formats are
|
||||
* initialized on the device.
|
||||
*/
|
||||
static int ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
struct v4l2_subdev_format format;
|
||||
|
||||
memset(&format, 0, sizeof(format));
|
||||
format.pad = IPIPE_PAD_SINK;
|
||||
format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
|
||||
format.format.width = 4096;
|
||||
format.format.height = 4096;
|
||||
ipipe_set_format(sd, fh ? fh->state : NULL, &format);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* V4L2 subdev video operations */
|
||||
static const struct v4l2_subdev_video_ops ipipe_v4l2_video_ops = {
|
||||
.s_stream = ipipe_set_stream,
|
||||
};
|
||||
|
||||
/* V4L2 subdev pad operations */
|
||||
static const struct v4l2_subdev_pad_ops ipipe_v4l2_pad_ops = {
|
||||
.enum_mbus_code = ipipe_enum_mbus_code,
|
||||
.enum_frame_size = ipipe_enum_frame_size,
|
||||
.get_fmt = ipipe_get_format,
|
||||
.set_fmt = ipipe_set_format,
|
||||
.link_validate = ipipe_link_validate,
|
||||
};
|
||||
|
||||
/* V4L2 subdev operations */
|
||||
static const struct v4l2_subdev_ops ipipe_v4l2_ops = {
|
||||
.video = &ipipe_v4l2_video_ops,
|
||||
.pad = &ipipe_v4l2_pad_ops,
|
||||
};
|
||||
|
||||
/* V4L2 subdev internal operations */
|
||||
static const struct v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = {
|
||||
.open = ipipe_init_formats,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Media entity operations
|
||||
*/
|
||||
|
||||
/*
|
||||
* ipipe_link_setup - Setup IPIPE connections
|
||||
* @entity: IPIPE media entity
|
||||
* @local: Pad at the local end of the link
|
||||
* @remote: Pad at the remote end of the link
|
||||
* @flags: Link flags
|
||||
*
|
||||
* return -EINVAL or zero on success
|
||||
*/
|
||||
static int ipipe_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 iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
|
||||
struct iss_device *iss = to_iss_device(ipipe);
|
||||
|
||||
if (!is_media_entity_v4l2_subdev(remote->entity))
|
||||
return -EINVAL;
|
||||
|
||||
switch (local->index) {
|
||||
case IPIPE_PAD_SINK:
|
||||
/* Read from IPIPEIF. */
|
||||
if (!(flags & MEDIA_LNK_FL_ENABLED)) {
|
||||
ipipe->input = IPIPE_INPUT_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ipipe->input != IPIPE_INPUT_NONE)
|
||||
return -EBUSY;
|
||||
|
||||
if (remote->entity == &iss->ipipeif.subdev.entity)
|
||||
ipipe->input = IPIPE_INPUT_IPIPEIF;
|
||||
|
||||
break;
|
||||
|
||||
case IPIPE_PAD_SOURCE_VP:
|
||||
/* Send to RESIZER */
|
||||
if (flags & MEDIA_LNK_FL_ENABLED) {
|
||||
if (ipipe->output & ~IPIPE_OUTPUT_VP)
|
||||
return -EBUSY;
|
||||
ipipe->output |= IPIPE_OUTPUT_VP;
|
||||
} else {
|
||||
ipipe->output &= ~IPIPE_OUTPUT_VP;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* media operations */
|
||||
static const struct media_entity_operations ipipe_media_ops = {
|
||||
.link_setup = ipipe_link_setup,
|
||||
.link_validate = v4l2_subdev_link_validate,
|
||||
};
|
||||
|
||||
/*
|
||||
* ipipe_init_entities - Initialize V4L2 subdev and media entity
|
||||
* @ipipe: ISS ISP IPIPE module
|
||||
*
|
||||
* Return 0 on success and a negative error code on failure.
|
||||
*/
|
||||
static int ipipe_init_entities(struct iss_ipipe_device *ipipe)
|
||||
{
|
||||
struct v4l2_subdev *sd = &ipipe->subdev;
|
||||
struct media_pad *pads = ipipe->pads;
|
||||
struct media_entity *me = &sd->entity;
|
||||
int ret;
|
||||
|
||||
ipipe->input = IPIPE_INPUT_NONE;
|
||||
|
||||
v4l2_subdev_init(sd, &ipipe_v4l2_ops);
|
||||
sd->internal_ops = &ipipe_v4l2_internal_ops;
|
||||
strscpy(sd->name, "OMAP4 ISS ISP IPIPE", sizeof(sd->name));
|
||||
sd->grp_id = BIT(16); /* group ID for iss subdevs */
|
||||
v4l2_set_subdevdata(sd, ipipe);
|
||||
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
|
||||
pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
|
||||
pads[IPIPE_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
|
||||
|
||||
me->ops = &ipipe_media_ops;
|
||||
ret = media_entity_pads_init(me, IPIPE_PADS_NUM, pads);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ipipe_init_formats(sd, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe)
|
||||
{
|
||||
v4l2_device_unregister_subdev(&ipipe->subdev);
|
||||
}
|
||||
|
||||
int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe,
|
||||
struct v4l2_device *vdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Register the subdev and video node. */
|
||||
ret = v4l2_device_register_subdev(vdev, &ipipe->subdev);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
omap4iss_ipipe_unregister_entities(ipipe);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ISP IPIPE initialisation and cleanup
|
||||
*/
|
||||
|
||||
/*
|
||||
* omap4iss_ipipe_init - IPIPE module initialization.
|
||||
* @iss: Device pointer specific to the OMAP4 ISS.
|
||||
*
|
||||
* TODO: Get the initialisation values from platform data.
|
||||
*
|
||||
* Return 0 on success or a negative error code otherwise.
|
||||
*/
|
||||
int omap4iss_ipipe_init(struct iss_device *iss)
|
||||
{
|
||||
struct iss_ipipe_device *ipipe = &iss->ipipe;
|
||||
|
||||
ipipe->state = ISS_PIPELINE_STREAM_STOPPED;
|
||||
init_waitqueue_head(&ipipe->wait);
|
||||
|
||||
return ipipe_init_entities(ipipe);
|
||||
}
|
||||
|
||||
/*
|
||||
* omap4iss_ipipe_cleanup - IPIPE module cleanup.
|
||||
* @iss: Device pointer specific to the OMAP4 ISS.
|
||||
*/
|
||||
void omap4iss_ipipe_cleanup(struct iss_device *iss)
|
||||
{
|
||||
struct iss_ipipe_device *ipipe = &iss->ipipe;
|
||||
|
||||
media_entity_cleanup(&ipipe->subdev.entity);
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - ISP IPIPE module
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef OMAP4_ISS_IPIPE_H
|
||||
#define OMAP4_ISS_IPIPE_H
|
||||
|
||||
#include "iss_video.h"
|
||||
|
||||
enum ipipe_input_entity {
|
||||
IPIPE_INPUT_NONE,
|
||||
IPIPE_INPUT_IPIPEIF,
|
||||
};
|
||||
|
||||
#define IPIPE_OUTPUT_VP BIT(0)
|
||||
|
||||
/* Sink and source IPIPE pads */
|
||||
#define IPIPE_PAD_SINK 0
|
||||
#define IPIPE_PAD_SOURCE_VP 1
|
||||
#define IPIPE_PADS_NUM 2
|
||||
|
||||
/*
|
||||
* struct iss_ipipe_device - Structure for the IPIPE module to store its own
|
||||
* information
|
||||
* @subdev: V4L2 subdevice
|
||||
* @pads: Sink and source media entity pads
|
||||
* @formats: Active video formats
|
||||
* @input: Active input
|
||||
* @output: Active outputs
|
||||
* @error: A hardware error occurred during capture
|
||||
* @state: Streaming state
|
||||
* @wait: Wait queue used to stop the module
|
||||
* @stopping: Stopping state
|
||||
*/
|
||||
struct iss_ipipe_device {
|
||||
struct v4l2_subdev subdev;
|
||||
struct media_pad pads[IPIPE_PADS_NUM];
|
||||
struct v4l2_mbus_framefmt formats[IPIPE_PADS_NUM];
|
||||
|
||||
enum ipipe_input_entity input;
|
||||
unsigned int output;
|
||||
unsigned int error;
|
||||
|
||||
enum iss_pipeline_stream_state state;
|
||||
wait_queue_head_t wait;
|
||||
atomic_t stopping;
|
||||
};
|
||||
|
||||
struct iss_device;
|
||||
|
||||
int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe,
|
||||
struct v4l2_device *vdev);
|
||||
void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe);
|
||||
|
||||
int omap4iss_ipipe_init(struct iss_device *iss);
|
||||
void omap4iss_ipipe_cleanup(struct iss_device *iss);
|
||||
|
||||
#endif /* OMAP4_ISS_IPIPE_H */
|
@ -1,844 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "iss.h"
|
||||
#include "iss_regs.h"
|
||||
#include "iss_ipipeif.h"
|
||||
|
||||
static const unsigned int ipipeif_fmts[] = {
|
||||
MEDIA_BUS_FMT_SGRBG10_1X10,
|
||||
MEDIA_BUS_FMT_SRGGB10_1X10,
|
||||
MEDIA_BUS_FMT_SBGGR10_1X10,
|
||||
MEDIA_BUS_FMT_SGBRG10_1X10,
|
||||
MEDIA_BUS_FMT_UYVY8_1X16,
|
||||
MEDIA_BUS_FMT_YUYV8_1X16,
|
||||
};
|
||||
|
||||
/*
|
||||
* ipipeif_print_status - Print current IPIPEIF Module register values.
|
||||
* @ipipeif: Pointer to ISS ISP IPIPEIF device.
|
||||
*
|
||||
* Also prints other debug information stored in the IPIPEIF module.
|
||||
*/
|
||||
#define IPIPEIF_PRINT_REGISTER(iss, name)\
|
||||
dev_dbg(iss->dev, "###IPIPEIF " #name "=0x%08x\n", \
|
||||
iss_reg_read(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_##name))
|
||||
|
||||
#define ISIF_PRINT_REGISTER(iss, name)\
|
||||
dev_dbg(iss->dev, "###ISIF " #name "=0x%08x\n", \
|
||||
iss_reg_read(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_##name))
|
||||
|
||||
#define ISP5_PRINT_REGISTER(iss, name)\
|
||||
dev_dbg(iss->dev, "###ISP5 " #name "=0x%08x\n", \
|
||||
iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_##name))
|
||||
|
||||
static void ipipeif_print_status(struct iss_ipipeif_device *ipipeif)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(ipipeif);
|
||||
|
||||
dev_dbg(iss->dev, "-------------IPIPEIF Register dump-------------\n");
|
||||
|
||||
IPIPEIF_PRINT_REGISTER(iss, CFG1);
|
||||
IPIPEIF_PRINT_REGISTER(iss, CFG2);
|
||||
|
||||
ISIF_PRINT_REGISTER(iss, SYNCEN);
|
||||
ISIF_PRINT_REGISTER(iss, CADU);
|
||||
ISIF_PRINT_REGISTER(iss, CADL);
|
||||
ISIF_PRINT_REGISTER(iss, MODESET);
|
||||
ISIF_PRINT_REGISTER(iss, CCOLP);
|
||||
ISIF_PRINT_REGISTER(iss, SPH);
|
||||
ISIF_PRINT_REGISTER(iss, LNH);
|
||||
ISIF_PRINT_REGISTER(iss, LNV);
|
||||
ISIF_PRINT_REGISTER(iss, VDINT(0));
|
||||
ISIF_PRINT_REGISTER(iss, HSIZE);
|
||||
|
||||
ISP5_PRINT_REGISTER(iss, SYSCONFIG);
|
||||
ISP5_PRINT_REGISTER(iss, CTRL);
|
||||
ISP5_PRINT_REGISTER(iss, IRQSTATUS(0));
|
||||
ISP5_PRINT_REGISTER(iss, IRQENABLE_SET(0));
|
||||
ISP5_PRINT_REGISTER(iss, IRQENABLE_CLR(0));
|
||||
|
||||
dev_dbg(iss->dev, "-----------------------------------------------\n");
|
||||
}
|
||||
|
||||
static void ipipeif_write_enable(struct iss_ipipeif_device *ipipeif, u8 enable)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(ipipeif);
|
||||
|
||||
iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SYNCEN,
|
||||
ISIF_SYNCEN_DWEN, enable ? ISIF_SYNCEN_DWEN : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipeif_enable - Enable/Disable IPIPEIF.
|
||||
* @enable: enable flag
|
||||
*
|
||||
*/
|
||||
static void ipipeif_enable(struct iss_ipipeif_device *ipipeif, u8 enable)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(ipipeif);
|
||||
|
||||
iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SYNCEN,
|
||||
ISIF_SYNCEN_SYEN, enable ? ISIF_SYNCEN_SYEN : 0);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Format- and pipeline-related configuration helpers
|
||||
*/
|
||||
|
||||
/*
|
||||
* ipipeif_set_outaddr - Set memory address to save output image
|
||||
* @ipipeif: Pointer to ISP IPIPEIF device.
|
||||
* @addr: 32-bit memory address aligned on 32 byte boundary.
|
||||
*
|
||||
* Sets the memory address where the output will be saved.
|
||||
*/
|
||||
static void ipipeif_set_outaddr(struct iss_ipipeif_device *ipipeif, u32 addr)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(ipipeif);
|
||||
|
||||
/* Save address split in Base Address H & L */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CADU,
|
||||
(addr >> (16 + 5)) & ISIF_CADU_MASK);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CADL,
|
||||
(addr >> 5) & ISIF_CADL_MASK);
|
||||
}
|
||||
|
||||
static void ipipeif_configure(struct iss_ipipeif_device *ipipeif)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(ipipeif);
|
||||
const struct iss_format_info *info;
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
u32 isif_ccolp = 0;
|
||||
|
||||
omap4iss_configure_bridge(iss, ipipeif->input);
|
||||
|
||||
/* IPIPEIF_PAD_SINK */
|
||||
format = &ipipeif->formats[IPIPEIF_PAD_SINK];
|
||||
|
||||
/* IPIPEIF with YUV422 input from ISIF */
|
||||
iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG1,
|
||||
IPIPEIF_CFG1_INPSRC1_MASK | IPIPEIF_CFG1_INPSRC2_MASK);
|
||||
|
||||
/* Select ISIF/IPIPEIF input format */
|
||||
switch (format->code) {
|
||||
case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||
case MEDIA_BUS_FMT_YUYV8_1X16:
|
||||
iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_MODESET,
|
||||
ISIF_MODESET_CCDMD | ISIF_MODESET_INPMOD_MASK |
|
||||
ISIF_MODESET_CCDW_MASK,
|
||||
ISIF_MODESET_INPMOD_YCBCR16);
|
||||
|
||||
iss_reg_update(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG2,
|
||||
IPIPEIF_CFG2_YUV8, IPIPEIF_CFG2_YUV16);
|
||||
|
||||
break;
|
||||
case MEDIA_BUS_FMT_SGRBG10_1X10:
|
||||
isif_ccolp = ISIF_CCOLP_CP0_F0_GR |
|
||||
ISIF_CCOLP_CP1_F0_R |
|
||||
ISIF_CCOLP_CP2_F0_B |
|
||||
ISIF_CCOLP_CP3_F0_GB;
|
||||
goto cont_raw;
|
||||
case MEDIA_BUS_FMT_SRGGB10_1X10:
|
||||
isif_ccolp = ISIF_CCOLP_CP0_F0_R |
|
||||
ISIF_CCOLP_CP1_F0_GR |
|
||||
ISIF_CCOLP_CP2_F0_GB |
|
||||
ISIF_CCOLP_CP3_F0_B;
|
||||
goto cont_raw;
|
||||
case MEDIA_BUS_FMT_SBGGR10_1X10:
|
||||
isif_ccolp = ISIF_CCOLP_CP0_F0_B |
|
||||
ISIF_CCOLP_CP1_F0_GB |
|
||||
ISIF_CCOLP_CP2_F0_GR |
|
||||
ISIF_CCOLP_CP3_F0_R;
|
||||
goto cont_raw;
|
||||
case MEDIA_BUS_FMT_SGBRG10_1X10:
|
||||
isif_ccolp = ISIF_CCOLP_CP0_F0_GB |
|
||||
ISIF_CCOLP_CP1_F0_B |
|
||||
ISIF_CCOLP_CP2_F0_R |
|
||||
ISIF_CCOLP_CP3_F0_GR;
|
||||
cont_raw:
|
||||
iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG2,
|
||||
IPIPEIF_CFG2_YUV16);
|
||||
|
||||
iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_MODESET,
|
||||
ISIF_MODESET_CCDMD | ISIF_MODESET_INPMOD_MASK |
|
||||
ISIF_MODESET_CCDW_MASK, ISIF_MODESET_INPMOD_RAW |
|
||||
ISIF_MODESET_CCDW_2BIT);
|
||||
|
||||
info = omap4iss_video_format_info(format->code);
|
||||
iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CGAMMAWD,
|
||||
ISIF_CGAMMAWD_GWDI_MASK,
|
||||
ISIF_CGAMMAWD_GWDI(info->bpp));
|
||||
|
||||
/* Set RAW Bayer pattern */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CCOLP,
|
||||
isif_ccolp);
|
||||
break;
|
||||
}
|
||||
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SPH, 0 & ISIF_SPH_MASK);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_LNH,
|
||||
(format->width - 1) & ISIF_LNH_MASK);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_LNV,
|
||||
(format->height - 1) & ISIF_LNV_MASK);
|
||||
|
||||
/* Generate ISIF0 on the last line of the image */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_VDINT(0),
|
||||
format->height - 1);
|
||||
|
||||
/* IPIPEIF_PAD_SOURCE_ISIF_SF */
|
||||
format = &ipipeif->formats[IPIPEIF_PAD_SOURCE_ISIF_SF];
|
||||
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_HSIZE,
|
||||
(ipipeif->video_out.bpl_value >> 5) &
|
||||
ISIF_HSIZE_HSIZE_MASK);
|
||||
|
||||
/* IPIPEIF_PAD_SOURCE_VP */
|
||||
/* Do nothing? */
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Interrupt handling
|
||||
*/
|
||||
|
||||
static void ipipeif_isr_buffer(struct iss_ipipeif_device *ipipeif)
|
||||
{
|
||||
struct iss_buffer *buffer;
|
||||
|
||||
/* The ISIF generates VD0 interrupts even when writes are disabled.
|
||||
* deal with it anyway). Disabling the ISIF when no buffer is available
|
||||
* is thus not be enough, we need to handle the situation explicitly.
|
||||
*/
|
||||
if (list_empty(&ipipeif->video_out.dmaqueue))
|
||||
return;
|
||||
|
||||
ipipeif_write_enable(ipipeif, 0);
|
||||
|
||||
buffer = omap4iss_video_buffer_next(&ipipeif->video_out);
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
ipipeif_set_outaddr(ipipeif, buffer->iss_addr);
|
||||
|
||||
ipipeif_write_enable(ipipeif, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* omap4iss_ipipeif_isr - Configure ipipeif during interframe time.
|
||||
* @ipipeif: Pointer to ISP IPIPEIF device.
|
||||
* @events: IPIPEIF events
|
||||
*/
|
||||
void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events)
|
||||
{
|
||||
if (omap4iss_module_sync_is_stopping(&ipipeif->wait,
|
||||
&ipipeif->stopping))
|
||||
return;
|
||||
|
||||
if ((events & ISP5_IRQ_ISIF_INT(0)) &&
|
||||
(ipipeif->output & IPIPEIF_OUTPUT_MEMORY))
|
||||
ipipeif_isr_buffer(ipipeif);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ISP video operations
|
||||
*/
|
||||
|
||||
static int ipipeif_video_queue(struct iss_video *video,
|
||||
struct iss_buffer *buffer)
|
||||
{
|
||||
struct iss_ipipeif_device *ipipeif = container_of(video,
|
||||
struct iss_ipipeif_device, video_out);
|
||||
|
||||
if (!(ipipeif->output & IPIPEIF_OUTPUT_MEMORY))
|
||||
return -ENODEV;
|
||||
|
||||
ipipeif_set_outaddr(ipipeif, buffer->iss_addr);
|
||||
|
||||
/*
|
||||
* If streaming was enabled before there was a buffer queued
|
||||
* or underrun happened in the ISR, the hardware was not enabled
|
||||
* and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set.
|
||||
* Enable it now.
|
||||
*/
|
||||
if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
|
||||
if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
|
||||
ipipeif_write_enable(ipipeif, 1);
|
||||
ipipeif_enable(ipipeif, 1);
|
||||
iss_video_dmaqueue_flags_clr(video);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iss_video_operations ipipeif_video_ops = {
|
||||
.queue = ipipeif_video_queue,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* V4L2 subdev operations
|
||||
*/
|
||||
|
||||
#define IPIPEIF_DRV_SUBCLK_MASK (OMAP4_ISS_ISP_SUBCLK_IPIPEIF |\
|
||||
OMAP4_ISS_ISP_SUBCLK_ISIF)
|
||||
/*
|
||||
* ipipeif_set_stream - Enable/Disable streaming on the IPIPEIF module
|
||||
* @sd: ISP IPIPEIF V4L2 subdevice
|
||||
* @enable: Enable/disable stream
|
||||
*/
|
||||
static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
|
||||
struct iss_device *iss = to_iss_device(ipipeif);
|
||||
struct iss_video *video_out = &ipipeif->video_out;
|
||||
int ret = 0;
|
||||
|
||||
if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED) {
|
||||
if (enable == ISS_PIPELINE_STREAM_STOPPED)
|
||||
return 0;
|
||||
|
||||
omap4iss_isp_subclk_enable(iss, IPIPEIF_DRV_SUBCLK_MASK);
|
||||
}
|
||||
|
||||
switch (enable) {
|
||||
case ISS_PIPELINE_STREAM_CONTINUOUS:
|
||||
|
||||
ipipeif_configure(ipipeif);
|
||||
ipipeif_print_status(ipipeif);
|
||||
|
||||
/*
|
||||
* When outputting to memory with no buffer available, let the
|
||||
* buffer queue handler start the hardware. A DMA queue flag
|
||||
* ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
|
||||
* a buffer available.
|
||||
*/
|
||||
if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY &&
|
||||
!(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED))
|
||||
break;
|
||||
|
||||
atomic_set(&ipipeif->stopping, 0);
|
||||
if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
|
||||
ipipeif_write_enable(ipipeif, 1);
|
||||
ipipeif_enable(ipipeif, 1);
|
||||
iss_video_dmaqueue_flags_clr(video_out);
|
||||
break;
|
||||
|
||||
case ISS_PIPELINE_STREAM_STOPPED:
|
||||
if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED)
|
||||
return 0;
|
||||
if (omap4iss_module_sync_idle(&sd->entity, &ipipeif->wait,
|
||||
&ipipeif->stopping))
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
|
||||
ipipeif_write_enable(ipipeif, 0);
|
||||
ipipeif_enable(ipipeif, 0);
|
||||
omap4iss_isp_subclk_disable(iss, IPIPEIF_DRV_SUBCLK_MASK);
|
||||
iss_video_dmaqueue_flags_clr(video_out);
|
||||
break;
|
||||
}
|
||||
|
||||
ipipeif->state = enable;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct v4l2_mbus_framefmt *
|
||||
__ipipeif_get_format(struct iss_ipipeif_device *ipipeif,
|
||||
struct v4l2_subdev_state *sd_state, unsigned int pad,
|
||||
enum v4l2_subdev_format_whence which)
|
||||
{
|
||||
if (which == V4L2_SUBDEV_FORMAT_TRY)
|
||||
return v4l2_subdev_state_get_format(sd_state, pad);
|
||||
return &ipipeif->formats[pad];
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipeif_try_format - Try video format on a pad
|
||||
* @ipipeif: ISS IPIPEIF device
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @pad: Pad number
|
||||
* @fmt: Format
|
||||
*/
|
||||
static void
|
||||
ipipeif_try_format(struct iss_ipipeif_device *ipipeif,
|
||||
struct v4l2_subdev_state *sd_state, unsigned int pad,
|
||||
struct v4l2_mbus_framefmt *fmt,
|
||||
enum v4l2_subdev_format_whence which)
|
||||
{
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
unsigned int width = fmt->width;
|
||||
unsigned int height = fmt->height;
|
||||
unsigned int i;
|
||||
|
||||
switch (pad) {
|
||||
case IPIPEIF_PAD_SINK:
|
||||
/* TODO: If the IPIPEIF output formatter pad is connected
|
||||
* directly to the resizer, only YUV formats can be used.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(ipipeif_fmts); i++) {
|
||||
if (fmt->code == ipipeif_fmts[i])
|
||||
break;
|
||||
}
|
||||
|
||||
/* If not found, use SGRBG10 as default */
|
||||
if (i >= ARRAY_SIZE(ipipeif_fmts))
|
||||
fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
|
||||
|
||||
/* Clamp the input size. */
|
||||
fmt->width = clamp_t(u32, width, 1, 8192);
|
||||
fmt->height = clamp_t(u32, height, 1, 8192);
|
||||
break;
|
||||
|
||||
case IPIPEIF_PAD_SOURCE_ISIF_SF:
|
||||
format = __ipipeif_get_format(ipipeif, sd_state,
|
||||
IPIPEIF_PAD_SINK,
|
||||
which);
|
||||
memcpy(fmt, format, sizeof(*fmt));
|
||||
|
||||
/* The data formatter truncates the number of horizontal output
|
||||
* pixels to a multiple of 16. To avoid clipping data, allow
|
||||
* callers to request an output size bigger than the input size
|
||||
* up to the nearest multiple of 16.
|
||||
*/
|
||||
fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15);
|
||||
fmt->width &= ~15;
|
||||
fmt->height = clamp_t(u32, height, 32, fmt->height);
|
||||
break;
|
||||
|
||||
case IPIPEIF_PAD_SOURCE_VP:
|
||||
format = __ipipeif_get_format(ipipeif, sd_state,
|
||||
IPIPEIF_PAD_SINK,
|
||||
which);
|
||||
memcpy(fmt, format, sizeof(*fmt));
|
||||
|
||||
fmt->width = clamp_t(u32, width, 32, fmt->width);
|
||||
fmt->height = clamp_t(u32, height, 32, fmt->height);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Data is written to memory unpacked, each 10-bit or 12-bit pixel is
|
||||
* stored on 2 bytes.
|
||||
*/
|
||||
fmt->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
fmt->field = V4L2_FIELD_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipeif_enum_mbus_code - Handle pixel format enumeration
|
||||
* @sd : pointer to v4l2 subdev structure
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @code : pointer to v4l2_subdev_mbus_code_enum structure
|
||||
* return -EINVAL or zero on success
|
||||
*/
|
||||
static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_mbus_code_enum *code)
|
||||
{
|
||||
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
|
||||
switch (code->pad) {
|
||||
case IPIPEIF_PAD_SINK:
|
||||
if (code->index >= ARRAY_SIZE(ipipeif_fmts))
|
||||
return -EINVAL;
|
||||
|
||||
code->code = ipipeif_fmts[code->index];
|
||||
break;
|
||||
|
||||
case IPIPEIF_PAD_SOURCE_ISIF_SF:
|
||||
case IPIPEIF_PAD_SOURCE_VP:
|
||||
/* No format conversion inside IPIPEIF */
|
||||
if (code->index != 0)
|
||||
return -EINVAL;
|
||||
|
||||
format = __ipipeif_get_format(ipipeif, sd_state,
|
||||
IPIPEIF_PAD_SINK,
|
||||
code->which);
|
||||
|
||||
code->code = format->code;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_frame_size_enum *fse)
|
||||
{
|
||||
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt format;
|
||||
|
||||
if (fse->index != 0)
|
||||
return -EINVAL;
|
||||
|
||||
format.code = fse->code;
|
||||
format.width = 1;
|
||||
format.height = 1;
|
||||
ipipeif_try_format(ipipeif, sd_state, fse->pad, &format, fse->which);
|
||||
fse->min_width = format.width;
|
||||
fse->min_height = format.height;
|
||||
|
||||
if (format.code != fse->code)
|
||||
return -EINVAL;
|
||||
|
||||
format.code = fse->code;
|
||||
format.width = -1;
|
||||
format.height = -1;
|
||||
ipipeif_try_format(ipipeif, sd_state, fse->pad, &format, fse->which);
|
||||
fse->max_width = format.width;
|
||||
fse->max_height = format.height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipeif_get_format - Retrieve the video format on a pad
|
||||
* @sd : ISP IPIPEIF V4L2 subdevice
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @fmt: Format
|
||||
*
|
||||
* Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
|
||||
* to the format type.
|
||||
*/
|
||||
static int ipipeif_get_format(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_format *fmt)
|
||||
{
|
||||
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
|
||||
format = __ipipeif_get_format(ipipeif, sd_state, fmt->pad, fmt->which);
|
||||
if (!format)
|
||||
return -EINVAL;
|
||||
|
||||
fmt->format = *format;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipeif_set_format - Set the video format on a pad
|
||||
* @sd : ISP IPIPEIF V4L2 subdevice
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @fmt: Format
|
||||
*
|
||||
* Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
|
||||
* to the format type.
|
||||
*/
|
||||
static int ipipeif_set_format(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_format *fmt)
|
||||
{
|
||||
struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
|
||||
format = __ipipeif_get_format(ipipeif, sd_state, fmt->pad, fmt->which);
|
||||
if (!format)
|
||||
return -EINVAL;
|
||||
|
||||
ipipeif_try_format(ipipeif, sd_state, fmt->pad, &fmt->format,
|
||||
fmt->which);
|
||||
*format = fmt->format;
|
||||
|
||||
/* Propagate the format from sink to source */
|
||||
if (fmt->pad == IPIPEIF_PAD_SINK) {
|
||||
format = __ipipeif_get_format(ipipeif, sd_state,
|
||||
IPIPEIF_PAD_SOURCE_ISIF_SF,
|
||||
fmt->which);
|
||||
*format = fmt->format;
|
||||
ipipeif_try_format(ipipeif, sd_state,
|
||||
IPIPEIF_PAD_SOURCE_ISIF_SF,
|
||||
format, fmt->which);
|
||||
|
||||
format = __ipipeif_get_format(ipipeif, sd_state,
|
||||
IPIPEIF_PAD_SOURCE_VP,
|
||||
fmt->which);
|
||||
*format = fmt->format;
|
||||
ipipeif_try_format(ipipeif, sd_state, IPIPEIF_PAD_SOURCE_VP,
|
||||
format,
|
||||
fmt->which);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipipeif_link_validate(struct v4l2_subdev *sd,
|
||||
struct media_link *link,
|
||||
struct v4l2_subdev_format *source_fmt,
|
||||
struct v4l2_subdev_format *sink_fmt)
|
||||
{
|
||||
/* Check if the two ends match */
|
||||
if (source_fmt->format.width != sink_fmt->format.width ||
|
||||
source_fmt->format.height != sink_fmt->format.height)
|
||||
return -EPIPE;
|
||||
|
||||
if (source_fmt->format.code != sink_fmt->format.code)
|
||||
return -EPIPE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ipipeif_init_formats - Initialize formats on all pads
|
||||
* @sd: ISP IPIPEIF V4L2 subdevice
|
||||
* @fh: V4L2 subdev file handle
|
||||
*
|
||||
* Initialize all pad formats with default values. If fh is not NULL, try
|
||||
* formats are initialized on the file handle. Otherwise active formats are
|
||||
* initialized on the device.
|
||||
*/
|
||||
static int ipipeif_init_formats(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
struct v4l2_subdev_format format;
|
||||
|
||||
memset(&format, 0, sizeof(format));
|
||||
format.pad = IPIPEIF_PAD_SINK;
|
||||
format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
|
||||
format.format.width = 4096;
|
||||
format.format.height = 4096;
|
||||
ipipeif_set_format(sd, fh ? fh->state : NULL, &format);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* V4L2 subdev video operations */
|
||||
static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = {
|
||||
.s_stream = ipipeif_set_stream,
|
||||
};
|
||||
|
||||
/* V4L2 subdev pad operations */
|
||||
static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = {
|
||||
.enum_mbus_code = ipipeif_enum_mbus_code,
|
||||
.enum_frame_size = ipipeif_enum_frame_size,
|
||||
.get_fmt = ipipeif_get_format,
|
||||
.set_fmt = ipipeif_set_format,
|
||||
.link_validate = ipipeif_link_validate,
|
||||
};
|
||||
|
||||
/* V4L2 subdev operations */
|
||||
static const struct v4l2_subdev_ops ipipeif_v4l2_ops = {
|
||||
.video = &ipipeif_v4l2_video_ops,
|
||||
.pad = &ipipeif_v4l2_pad_ops,
|
||||
};
|
||||
|
||||
/* V4L2 subdev internal operations */
|
||||
static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = {
|
||||
.open = ipipeif_init_formats,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Media entity operations
|
||||
*/
|
||||
|
||||
/*
|
||||
* ipipeif_link_setup - Setup IPIPEIF connections
|
||||
* @entity: IPIPEIF media entity
|
||||
* @local: Pad at the local end of the link
|
||||
* @remote: Pad at the remote end of the link
|
||||
* @flags: Link flags
|
||||
*
|
||||
* return -EINVAL or zero on success
|
||||
*/
|
||||
static int ipipeif_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 iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
|
||||
struct iss_device *iss = to_iss_device(ipipeif);
|
||||
unsigned int index = local->index;
|
||||
|
||||
/* FIXME: this is actually a hack! */
|
||||
if (is_media_entity_v4l2_subdev(remote->entity))
|
||||
index |= 2 << 16;
|
||||
|
||||
switch (index) {
|
||||
case IPIPEIF_PAD_SINK | 2 << 16:
|
||||
/* Read from the sensor CSI2a or CSI2b. */
|
||||
if (!(flags & MEDIA_LNK_FL_ENABLED)) {
|
||||
ipipeif->input = IPIPEIF_INPUT_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ipipeif->input != IPIPEIF_INPUT_NONE)
|
||||
return -EBUSY;
|
||||
|
||||
if (remote->entity == &iss->csi2a.subdev.entity)
|
||||
ipipeif->input = IPIPEIF_INPUT_CSI2A;
|
||||
else if (remote->entity == &iss->csi2b.subdev.entity)
|
||||
ipipeif->input = IPIPEIF_INPUT_CSI2B;
|
||||
|
||||
break;
|
||||
|
||||
case IPIPEIF_PAD_SOURCE_ISIF_SF:
|
||||
/* Write to memory */
|
||||
if (flags & MEDIA_LNK_FL_ENABLED) {
|
||||
if (ipipeif->output & ~IPIPEIF_OUTPUT_MEMORY)
|
||||
return -EBUSY;
|
||||
ipipeif->output |= IPIPEIF_OUTPUT_MEMORY;
|
||||
} else {
|
||||
ipipeif->output &= ~IPIPEIF_OUTPUT_MEMORY;
|
||||
}
|
||||
break;
|
||||
|
||||
case IPIPEIF_PAD_SOURCE_VP | 2 << 16:
|
||||
/* Send to IPIPE/RESIZER */
|
||||
if (flags & MEDIA_LNK_FL_ENABLED) {
|
||||
if (ipipeif->output & ~IPIPEIF_OUTPUT_VP)
|
||||
return -EBUSY;
|
||||
ipipeif->output |= IPIPEIF_OUTPUT_VP;
|
||||
} else {
|
||||
ipipeif->output &= ~IPIPEIF_OUTPUT_VP;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* media operations */
|
||||
static const struct media_entity_operations ipipeif_media_ops = {
|
||||
.link_setup = ipipeif_link_setup,
|
||||
.link_validate = v4l2_subdev_link_validate,
|
||||
};
|
||||
|
||||
/*
|
||||
* ipipeif_init_entities - Initialize V4L2 subdev and media entity
|
||||
* @ipipeif: ISS ISP IPIPEIF module
|
||||
*
|
||||
* Return 0 on success and a negative error code on failure.
|
||||
*/
|
||||
static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif)
|
||||
{
|
||||
struct v4l2_subdev *sd = &ipipeif->subdev;
|
||||
struct media_pad *pads = ipipeif->pads;
|
||||
struct media_entity *me = &sd->entity;
|
||||
int ret;
|
||||
|
||||
ipipeif->input = IPIPEIF_INPUT_NONE;
|
||||
|
||||
v4l2_subdev_init(sd, &ipipeif_v4l2_ops);
|
||||
sd->internal_ops = &ipipeif_v4l2_internal_ops;
|
||||
strscpy(sd->name, "OMAP4 ISS ISP IPIPEIF", sizeof(sd->name));
|
||||
sd->grp_id = BIT(16); /* group ID for iss subdevs */
|
||||
v4l2_set_subdevdata(sd, ipipeif);
|
||||
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
|
||||
pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
|
||||
pads[IPIPEIF_PAD_SOURCE_ISIF_SF].flags = MEDIA_PAD_FL_SOURCE;
|
||||
pads[IPIPEIF_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
|
||||
|
||||
me->ops = &ipipeif_media_ops;
|
||||
ret = media_entity_pads_init(me, IPIPEIF_PADS_NUM, pads);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ipipeif_init_formats(sd, NULL);
|
||||
|
||||
ipipeif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
ipipeif->video_out.ops = &ipipeif_video_ops;
|
||||
ipipeif->video_out.iss = to_iss_device(ipipeif);
|
||||
ipipeif->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
|
||||
ipipeif->video_out.bpl_alignment = 32;
|
||||
ipipeif->video_out.bpl_zero_padding = 1;
|
||||
ipipeif->video_out.bpl_max = 0x1ffe0;
|
||||
|
||||
return omap4iss_video_init(&ipipeif->video_out, "ISP IPIPEIF");
|
||||
}
|
||||
|
||||
void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif)
|
||||
{
|
||||
v4l2_device_unregister_subdev(&ipipeif->subdev);
|
||||
omap4iss_video_unregister(&ipipeif->video_out);
|
||||
}
|
||||
|
||||
int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif,
|
||||
struct v4l2_device *vdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Register the subdev and video node. */
|
||||
ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = omap4iss_video_register(&ipipeif->video_out, vdev);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
omap4iss_ipipeif_unregister_entities(ipipeif);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ISP IPIPEIF initialisation and cleanup
|
||||
*/
|
||||
|
||||
/*
|
||||
* omap4iss_ipipeif_init - IPIPEIF module initialization.
|
||||
* @iss: Device pointer specific to the OMAP4 ISS.
|
||||
*
|
||||
* TODO: Get the initialisation values from platform data.
|
||||
*
|
||||
* Return 0 on success or a negative error code otherwise.
|
||||
*/
|
||||
int omap4iss_ipipeif_init(struct iss_device *iss)
|
||||
{
|
||||
struct iss_ipipeif_device *ipipeif = &iss->ipipeif;
|
||||
|
||||
ipipeif->state = ISS_PIPELINE_STREAM_STOPPED;
|
||||
init_waitqueue_head(&ipipeif->wait);
|
||||
|
||||
return ipipeif_init_entities(ipipeif);
|
||||
}
|
||||
|
||||
/*
|
||||
* omap4iss_ipipeif_create_links() - IPIPEIF pads links creation
|
||||
* @iss: Pointer to ISS device
|
||||
*
|
||||
* return negative error code or zero on success
|
||||
*/
|
||||
int omap4iss_ipipeif_create_links(struct iss_device *iss)
|
||||
{
|
||||
struct iss_ipipeif_device *ipipeif = &iss->ipipeif;
|
||||
|
||||
/* Connect the IPIPEIF subdev to the video node. */
|
||||
return media_create_pad_link(&ipipeif->subdev.entity,
|
||||
IPIPEIF_PAD_SOURCE_ISIF_SF,
|
||||
&ipipeif->video_out.video.entity, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* omap4iss_ipipeif_cleanup - IPIPEIF module cleanup.
|
||||
* @iss: Device pointer specific to the OMAP4 ISS.
|
||||
*/
|
||||
void omap4iss_ipipeif_cleanup(struct iss_device *iss)
|
||||
{
|
||||
struct iss_ipipeif_device *ipipeif = &iss->ipipeif;
|
||||
|
||||
media_entity_cleanup(&ipipeif->subdev.entity);
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef OMAP4_ISS_IPIPEIF_H
|
||||
#define OMAP4_ISS_IPIPEIF_H
|
||||
|
||||
#include "iss_video.h"
|
||||
|
||||
enum ipipeif_input_entity {
|
||||
IPIPEIF_INPUT_NONE,
|
||||
IPIPEIF_INPUT_CSI2A,
|
||||
IPIPEIF_INPUT_CSI2B
|
||||
};
|
||||
|
||||
#define IPIPEIF_OUTPUT_MEMORY BIT(0)
|
||||
#define IPIPEIF_OUTPUT_VP BIT(1)
|
||||
|
||||
/* Sink and source IPIPEIF pads */
|
||||
#define IPIPEIF_PAD_SINK 0
|
||||
#define IPIPEIF_PAD_SOURCE_ISIF_SF 1
|
||||
#define IPIPEIF_PAD_SOURCE_VP 2
|
||||
#define IPIPEIF_PADS_NUM 3
|
||||
|
||||
/*
|
||||
* struct iss_ipipeif_device - Structure for the IPIPEIF module to store its own
|
||||
* information
|
||||
* @subdev: V4L2 subdevice
|
||||
* @pads: Sink and source media entity pads
|
||||
* @formats: Active video formats
|
||||
* @input: Active input
|
||||
* @output: Active outputs
|
||||
* @video_out: Output video node
|
||||
* @error: A hardware error occurred during capture
|
||||
* @alaw: A-law compression enabled (1) or disabled (0)
|
||||
* @lpf: Low pass filter enabled (1) or disabled (0)
|
||||
* @obclamp: Optical-black clamp enabled (1) or disabled (0)
|
||||
* @fpc_en: Faulty pixels correction enabled (1) or disabled (0)
|
||||
* @blcomp: Black level compensation configuration
|
||||
* @clamp: Optical-black or digital clamp configuration
|
||||
* @fpc: Faulty pixels correction configuration
|
||||
* @lsc: Lens shading compensation configuration
|
||||
* @update: Bitmask of controls to update during the next interrupt
|
||||
* @shadow_update: Controls update in progress by userspace
|
||||
* @syncif: Interface synchronization configuration
|
||||
* @vpcfg: Video port configuration
|
||||
* @underrun: A buffer underrun occurred and a new buffer has been queued
|
||||
* @state: Streaming state
|
||||
* @lock: Serializes shadow_update with interrupt handler
|
||||
* @wait: Wait queue used to stop the module
|
||||
* @stopping: Stopping state
|
||||
* @ioctl_lock: Serializes ioctl calls and LSC requests freeing
|
||||
*/
|
||||
struct iss_ipipeif_device {
|
||||
struct v4l2_subdev subdev;
|
||||
struct media_pad pads[IPIPEIF_PADS_NUM];
|
||||
struct v4l2_mbus_framefmt formats[IPIPEIF_PADS_NUM];
|
||||
|
||||
enum ipipeif_input_entity input;
|
||||
unsigned int output;
|
||||
struct iss_video video_out;
|
||||
unsigned int error;
|
||||
|
||||
enum iss_pipeline_stream_state state;
|
||||
wait_queue_head_t wait;
|
||||
atomic_t stopping;
|
||||
};
|
||||
|
||||
struct iss_device;
|
||||
|
||||
int omap4iss_ipipeif_init(struct iss_device *iss);
|
||||
int omap4iss_ipipeif_create_links(struct iss_device *iss);
|
||||
void omap4iss_ipipeif_cleanup(struct iss_device *iss);
|
||||
int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif,
|
||||
struct v4l2_device *vdev);
|
||||
void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif);
|
||||
|
||||
int omap4iss_ipipeif_busy(struct iss_ipipeif_device *ipipeif);
|
||||
void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events);
|
||||
void omap4iss_ipipeif_restore_context(struct iss_device *iss);
|
||||
void omap4iss_ipipeif_max_rate(struct iss_ipipeif_device *ipipeif,
|
||||
unsigned int *max_rate);
|
||||
|
||||
#endif /* OMAP4_ISS_IPIPEIF_H */
|
@ -1,899 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - Register defines
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _OMAP4_ISS_REGS_H_
|
||||
#define _OMAP4_ISS_REGS_H_
|
||||
|
||||
/* ISS */
|
||||
#define ISS_HL_REVISION 0x0
|
||||
|
||||
#define ISS_HL_SYSCONFIG 0x10
|
||||
#define ISS_HL_SYSCONFIG_IDLEMODE_SHIFT 2
|
||||
#define ISS_HL_SYSCONFIG_IDLEMODE_FORCEIDLE 0x0
|
||||
#define ISS_HL_SYSCONFIG_IDLEMODE_NOIDLE 0x1
|
||||
#define ISS_HL_SYSCONFIG_IDLEMODE_SMARTIDLE 0x2
|
||||
#define ISS_HL_SYSCONFIG_SOFTRESET BIT(0)
|
||||
|
||||
#define ISS_HL_IRQSTATUS_RAW(i) (0x20 + (0x10 * (i)))
|
||||
#define ISS_HL_IRQSTATUS(i) (0x24 + (0x10 * (i)))
|
||||
#define ISS_HL_IRQENABLE_SET(i) (0x28 + (0x10 * (i)))
|
||||
#define ISS_HL_IRQENABLE_CLR(i) (0x2c + (0x10 * (i)))
|
||||
|
||||
#define ISS_HL_IRQ_HS_VS BIT(17)
|
||||
#define ISS_HL_IRQ_SIMCOP(i) BIT(12 + (i))
|
||||
#define ISS_HL_IRQ_BTE BIT(11)
|
||||
#define ISS_HL_IRQ_CBUFF BIT(10)
|
||||
#define ISS_HL_IRQ_CCP2(i) BIT((i) > 3 ? 16 : 14 + (i))
|
||||
#define ISS_HL_IRQ_CSIB BIT(5)
|
||||
#define ISS_HL_IRQ_CSIA BIT(4)
|
||||
#define ISS_HL_IRQ_ISP(i) BIT(i)
|
||||
|
||||
#define ISS_CTRL 0x80
|
||||
#define ISS_CTRL_CLK_DIV_MASK (3 << 4)
|
||||
#define ISS_CTRL_INPUT_SEL_MASK (3 << 2)
|
||||
#define ISS_CTRL_INPUT_SEL_CSI2A (0 << 2)
|
||||
#define ISS_CTRL_INPUT_SEL_CSI2B (1 << 2)
|
||||
#define ISS_CTRL_SYNC_DETECT_VS_RAISING (3 << 0)
|
||||
|
||||
#define ISS_CLKCTRL 0x84
|
||||
#define ISS_CLKCTRL_VPORT2_CLK BIT(30)
|
||||
#define ISS_CLKCTRL_VPORT1_CLK BIT(29)
|
||||
#define ISS_CLKCTRL_VPORT0_CLK BIT(28)
|
||||
#define ISS_CLKCTRL_CCP2 BIT(4)
|
||||
#define ISS_CLKCTRL_CSI2_B BIT(3)
|
||||
#define ISS_CLKCTRL_CSI2_A BIT(2)
|
||||
#define ISS_CLKCTRL_ISP BIT(1)
|
||||
#define ISS_CLKCTRL_SIMCOP BIT(0)
|
||||
|
||||
#define ISS_CLKSTAT 0x88
|
||||
#define ISS_CLKSTAT_VPORT2_CLK BIT(30)
|
||||
#define ISS_CLKSTAT_VPORT1_CLK BIT(29)
|
||||
#define ISS_CLKSTAT_VPORT0_CLK BIT(28)
|
||||
#define ISS_CLKSTAT_CCP2 BIT(4)
|
||||
#define ISS_CLKSTAT_CSI2_B BIT(3)
|
||||
#define ISS_CLKSTAT_CSI2_A BIT(2)
|
||||
#define ISS_CLKSTAT_ISP BIT(1)
|
||||
#define ISS_CLKSTAT_SIMCOP BIT(0)
|
||||
|
||||
#define ISS_PM_STATUS 0x8c
|
||||
#define ISS_PM_STATUS_CBUFF_PM_MASK (3 << 12)
|
||||
#define ISS_PM_STATUS_BTE_PM_MASK (3 << 10)
|
||||
#define ISS_PM_STATUS_SIMCOP_PM_MASK (3 << 8)
|
||||
#define ISS_PM_STATUS_ISP_PM_MASK (3 << 6)
|
||||
#define ISS_PM_STATUS_CCP2_PM_MASK (3 << 4)
|
||||
#define ISS_PM_STATUS_CSI2_B_PM_MASK (3 << 2)
|
||||
#define ISS_PM_STATUS_CSI2_A_PM_MASK (3 << 0)
|
||||
|
||||
#define REGISTER0 0x0
|
||||
#define REGISTER0_HSCLOCKCONFIG BIT(24)
|
||||
#define REGISTER0_THS_TERM_MASK (0xff << 8)
|
||||
#define REGISTER0_THS_TERM_SHIFT 8
|
||||
#define REGISTER0_THS_SETTLE_MASK (0xff << 0)
|
||||
#define REGISTER0_THS_SETTLE_SHIFT 0
|
||||
|
||||
#define REGISTER1 0x4
|
||||
#define REGISTER1_RESET_DONE_CTRLCLK BIT(29)
|
||||
#define REGISTER1_CLOCK_MISS_DETECTOR_STATUS BIT(25)
|
||||
#define REGISTER1_TCLK_TERM_MASK (0x3f << 18)
|
||||
#define REGISTER1_TCLK_TERM_SHIFT 18
|
||||
#define REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT 10
|
||||
#define REGISTER1_CTRLCLK_DIV_FACTOR_MASK (0x3 << 8)
|
||||
#define REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT 8
|
||||
#define REGISTER1_TCLK_SETTLE_MASK (0xff << 0)
|
||||
#define REGISTER1_TCLK_SETTLE_SHIFT 0
|
||||
|
||||
#define REGISTER2 0x8
|
||||
|
||||
#define CSI2_SYSCONFIG 0x10
|
||||
#define CSI2_SYSCONFIG_MSTANDBY_MODE_MASK (3 << 12)
|
||||
#define CSI2_SYSCONFIG_MSTANDBY_MODE_FORCE (0 << 12)
|
||||
#define CSI2_SYSCONFIG_MSTANDBY_MODE_NO (1 << 12)
|
||||
#define CSI2_SYSCONFIG_MSTANDBY_MODE_SMART (2 << 12)
|
||||
#define CSI2_SYSCONFIG_SOFT_RESET (1 << 1)
|
||||
#define CSI2_SYSCONFIG_AUTO_IDLE (1 << 0)
|
||||
|
||||
#define CSI2_SYSSTATUS 0x14
|
||||
#define CSI2_SYSSTATUS_RESET_DONE BIT(0)
|
||||
|
||||
#define CSI2_IRQSTATUS 0x18
|
||||
#define CSI2_IRQENABLE 0x1c
|
||||
|
||||
/* Shared bits across CSI2_IRQENABLE and IRQSTATUS */
|
||||
|
||||
#define CSI2_IRQ_OCP_ERR BIT(14)
|
||||
#define CSI2_IRQ_SHORT_PACKET BIT(13)
|
||||
#define CSI2_IRQ_ECC_CORRECTION BIT(12)
|
||||
#define CSI2_IRQ_ECC_NO_CORRECTION BIT(11)
|
||||
#define CSI2_IRQ_COMPLEXIO_ERR BIT(9)
|
||||
#define CSI2_IRQ_FIFO_OVF BIT(8)
|
||||
#define CSI2_IRQ_CONTEXT0 BIT(0)
|
||||
|
||||
#define CSI2_CTRL 0x40
|
||||
#define CSI2_CTRL_MFLAG_LEVH_MASK (7 << 20)
|
||||
#define CSI2_CTRL_MFLAG_LEVH_SHIFT 20
|
||||
#define CSI2_CTRL_MFLAG_LEVL_MASK (7 << 17)
|
||||
#define CSI2_CTRL_MFLAG_LEVL_SHIFT 17
|
||||
#define CSI2_CTRL_BURST_SIZE_EXPAND (1 << 16)
|
||||
#define CSI2_CTRL_VP_CLK_EN (1 << 15)
|
||||
#define CSI2_CTRL_NON_POSTED_WRITE (1 << 13)
|
||||
#define CSI2_CTRL_VP_ONLY_EN (1 << 11)
|
||||
#define CSI2_CTRL_VP_OUT_CTRL_MASK (3 << 8)
|
||||
#define CSI2_CTRL_VP_OUT_CTRL_SHIFT 8
|
||||
#define CSI2_CTRL_DBG_EN (1 << 7)
|
||||
#define CSI2_CTRL_BURST_SIZE_MASK (3 << 5)
|
||||
#define CSI2_CTRL_ENDIANNESS (1 << 4)
|
||||
#define CSI2_CTRL_FRAME (1 << 3)
|
||||
#define CSI2_CTRL_ECC_EN (1 << 2)
|
||||
#define CSI2_CTRL_IF_EN (1 << 0)
|
||||
|
||||
#define CSI2_DBG_H 0x44
|
||||
|
||||
#define CSI2_COMPLEXIO_CFG 0x50
|
||||
#define CSI2_COMPLEXIO_CFG_RESET_CTRL (1 << 30)
|
||||
#define CSI2_COMPLEXIO_CFG_RESET_DONE (1 << 29)
|
||||
#define CSI2_COMPLEXIO_CFG_PWD_CMD_MASK (3 << 27)
|
||||
#define CSI2_COMPLEXIO_CFG_PWD_CMD_OFF (0 << 27)
|
||||
#define CSI2_COMPLEXIO_CFG_PWD_CMD_ON (1 << 27)
|
||||
#define CSI2_COMPLEXIO_CFG_PWD_CMD_ULP (2 << 27)
|
||||
#define CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK (3 << 25)
|
||||
#define CSI2_COMPLEXIO_CFG_PWD_STATUS_OFF (0 << 25)
|
||||
#define CSI2_COMPLEXIO_CFG_PWD_STATUS_ON (1 << 25)
|
||||
#define CSI2_COMPLEXIO_CFG_PWD_STATUS_ULP (2 << 25)
|
||||
#define CSI2_COMPLEXIO_CFG_PWR_AUTO (1 << 24)
|
||||
#define CSI2_COMPLEXIO_CFG_DATA_POL(i) (1 << (((i) * 4) + 3))
|
||||
#define CSI2_COMPLEXIO_CFG_DATA_POSITION_MASK(i) (7 << ((i) * 4))
|
||||
#define CSI2_COMPLEXIO_CFG_DATA_POSITION_SHIFT(i) ((i) * 4)
|
||||
#define CSI2_COMPLEXIO_CFG_CLOCK_POL (1 << 3)
|
||||
#define CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK (7 << 0)
|
||||
#define CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT 0
|
||||
|
||||
#define CSI2_COMPLEXIO_IRQSTATUS 0x54
|
||||
|
||||
#define CSI2_SHORT_PACKET 0x5c
|
||||
|
||||
#define CSI2_COMPLEXIO_IRQENABLE 0x60
|
||||
|
||||
/* Shared bits across CSI2_COMPLEXIO_IRQENABLE and IRQSTATUS */
|
||||
#define CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT BIT(26)
|
||||
#define CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER BIT(25)
|
||||
#define CSI2_COMPLEXIO_IRQ_STATEULPM5 BIT(24)
|
||||
#define CSI2_COMPLEXIO_IRQ_STATEULPM4 BIT(23)
|
||||
#define CSI2_COMPLEXIO_IRQ_STATEULPM3 BIT(22)
|
||||
#define CSI2_COMPLEXIO_IRQ_STATEULPM2 BIT(21)
|
||||
#define CSI2_COMPLEXIO_IRQ_STATEULPM1 BIT(20)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRCONTROL5 BIT(19)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRCONTROL4 BIT(18)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRCONTROL3 BIT(17)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRCONTROL2 BIT(16)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRCONTROL1 BIT(15)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRESC5 BIT(14)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRESC4 BIT(13)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRESC3 BIT(12)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRESC2 BIT(11)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRESC1 BIT(10)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 BIT(9)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 BIT(8)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 BIT(7)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 BIT(6)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 BIT(5)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRSOTHS5 BIT(4)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRSOTHS4 BIT(3)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRSOTHS3 BIT(2)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRSOTHS2 BIT(1)
|
||||
#define CSI2_COMPLEXIO_IRQ_ERRSOTHS1 BIT(0)
|
||||
|
||||
#define CSI2_DBG_P 0x68
|
||||
|
||||
#define CSI2_TIMING 0x6c
|
||||
#define CSI2_TIMING_FORCE_RX_MODE_IO1 BIT(15)
|
||||
#define CSI2_TIMING_STOP_STATE_X16_IO1 BIT(14)
|
||||
#define CSI2_TIMING_STOP_STATE_X4_IO1 BIT(13)
|
||||
#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK (0x1fff << 0)
|
||||
#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT 0
|
||||
|
||||
#define CSI2_CTX_CTRL1(i) (0x70 + (0x20 * (i)))
|
||||
#define CSI2_CTX_CTRL1_GENERIC BIT(30)
|
||||
#define CSI2_CTX_CTRL1_TRANSCODE (0xf << 24)
|
||||
#define CSI2_CTX_CTRL1_FEC_NUMBER_MASK (0xff << 16)
|
||||
#define CSI2_CTX_CTRL1_COUNT_MASK (0xff << 8)
|
||||
#define CSI2_CTX_CTRL1_COUNT_SHIFT 8
|
||||
#define CSI2_CTX_CTRL1_EOF_EN BIT(7)
|
||||
#define CSI2_CTX_CTRL1_EOL_EN BIT(6)
|
||||
#define CSI2_CTX_CTRL1_CS_EN BIT(5)
|
||||
#define CSI2_CTX_CTRL1_COUNT_UNLOCK BIT(4)
|
||||
#define CSI2_CTX_CTRL1_PING_PONG BIT(3)
|
||||
#define CSI2_CTX_CTRL1_CTX_EN BIT(0)
|
||||
|
||||
#define CSI2_CTX_CTRL2(i) (0x74 + (0x20 * (i)))
|
||||
#define CSI2_CTX_CTRL2_FRAME_MASK (0xffff << 16)
|
||||
#define CSI2_CTX_CTRL2_FRAME_SHIFT 16
|
||||
#define CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT 13
|
||||
#define CSI2_CTX_CTRL2_USER_DEF_MAP_MASK \
|
||||
(0x3 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT)
|
||||
#define CSI2_CTX_CTRL2_VIRTUAL_ID_MASK (3 << 11)
|
||||
#define CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT 11
|
||||
#define CSI2_CTX_CTRL2_DPCM_PRED (1 << 10)
|
||||
#define CSI2_CTX_CTRL2_FORMAT_MASK (0x3ff << 0)
|
||||
#define CSI2_CTX_CTRL2_FORMAT_SHIFT 0
|
||||
|
||||
#define CSI2_CTX_DAT_OFST(i) (0x78 + (0x20 * (i)))
|
||||
#define CSI2_CTX_DAT_OFST_MASK (0xfff << 5)
|
||||
|
||||
#define CSI2_CTX_PING_ADDR(i) (0x7c + (0x20 * (i)))
|
||||
#define CSI2_CTX_PING_ADDR_MASK 0xffffffe0
|
||||
|
||||
#define CSI2_CTX_PONG_ADDR(i) (0x80 + (0x20 * (i)))
|
||||
#define CSI2_CTX_PONG_ADDR_MASK CSI2_CTX_PING_ADDR_MASK
|
||||
|
||||
#define CSI2_CTX_IRQENABLE(i) (0x84 + (0x20 * (i)))
|
||||
#define CSI2_CTX_IRQSTATUS(i) (0x88 + (0x20 * (i)))
|
||||
|
||||
#define CSI2_CTX_CTRL3(i) (0x8c + (0x20 * (i)))
|
||||
#define CSI2_CTX_CTRL3_ALPHA_SHIFT 5
|
||||
#define CSI2_CTX_CTRL3_ALPHA_MASK \
|
||||
(0x3fff << CSI2_CTX_CTRL3_ALPHA_SHIFT)
|
||||
|
||||
/* Shared bits across CSI2_CTX_IRQENABLE and IRQSTATUS */
|
||||
#define CSI2_CTX_IRQ_ECC_CORRECTION BIT(8)
|
||||
#define CSI2_CTX_IRQ_LINE_NUMBER BIT(7)
|
||||
#define CSI2_CTX_IRQ_FRAME_NUMBER BIT(6)
|
||||
#define CSI2_CTX_IRQ_CS BIT(5)
|
||||
#define CSI2_CTX_IRQ_LE BIT(3)
|
||||
#define CSI2_CTX_IRQ_LS BIT(2)
|
||||
#define CSI2_CTX_IRQ_FE BIT(1)
|
||||
#define CSI2_CTX_IRQ_FS BIT(0)
|
||||
|
||||
/* ISS BTE */
|
||||
#define BTE_CTRL (0x0030)
|
||||
#define BTE_CTRL_BW_LIMITER_MASK (0x3ff << 22)
|
||||
#define BTE_CTRL_BW_LIMITER_SHIFT 22
|
||||
|
||||
/* ISS ISP_SYS1 */
|
||||
#define ISP5_REVISION (0x0000)
|
||||
#define ISP5_SYSCONFIG (0x0010)
|
||||
#define ISP5_SYSCONFIG_STANDBYMODE_MASK (3 << 4)
|
||||
#define ISP5_SYSCONFIG_STANDBYMODE_FORCE (0 << 4)
|
||||
#define ISP5_SYSCONFIG_STANDBYMODE_NO (1 << 4)
|
||||
#define ISP5_SYSCONFIG_STANDBYMODE_SMART (2 << 4)
|
||||
#define ISP5_SYSCONFIG_SOFTRESET (1 << 1)
|
||||
|
||||
#define ISP5_IRQSTATUS(i) (0x0028 + (0x10 * (i)))
|
||||
#define ISP5_IRQENABLE_SET(i) (0x002c + (0x10 * (i)))
|
||||
#define ISP5_IRQENABLE_CLR(i) (0x0030 + (0x10 * (i)))
|
||||
|
||||
/* Bits shared for ISP5_IRQ* registers */
|
||||
#define ISP5_IRQ_OCP_ERR BIT(31)
|
||||
#define ISP5_IRQ_IPIPE_INT_DPC_RNEW1 BIT(29)
|
||||
#define ISP5_IRQ_IPIPE_INT_DPC_RNEW0 BIT(28)
|
||||
#define ISP5_IRQ_IPIPE_INT_DPC_INIT BIT(27)
|
||||
#define ISP5_IRQ_IPIPE_INT_EOF BIT(25)
|
||||
#define ISP5_IRQ_H3A_INT_EOF BIT(24)
|
||||
#define ISP5_IRQ_RSZ_INT_EOF1 BIT(23)
|
||||
#define ISP5_IRQ_RSZ_INT_EOF0 BIT(22)
|
||||
#define ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR BIT(19)
|
||||
#define ISP5_IRQ_RSZ_FIFO_OVF BIT(18)
|
||||
#define ISP5_IRQ_RSZ_INT_CYC_RSZB BIT(17)
|
||||
#define ISP5_IRQ_RSZ_INT_CYC_RSZA BIT(16)
|
||||
#define ISP5_IRQ_RSZ_INT_DMA BIT(15)
|
||||
#define ISP5_IRQ_RSZ_INT_LAST_PIX BIT(14)
|
||||
#define ISP5_IRQ_RSZ_INT_REG BIT(13)
|
||||
#define ISP5_IRQ_H3A_INT BIT(12)
|
||||
#define ISP5_IRQ_AF_INT BIT(11)
|
||||
#define ISP5_IRQ_AEW_INT BIT(10)
|
||||
#define ISP5_IRQ_IPIPEIF_IRQ BIT(9)
|
||||
#define ISP5_IRQ_IPIPE_INT_HST BIT(8)
|
||||
#define ISP5_IRQ_IPIPE_INT_BSC BIT(7)
|
||||
#define ISP5_IRQ_IPIPE_INT_DMA BIT(6)
|
||||
#define ISP5_IRQ_IPIPE_INT_LAST_PIX BIT(5)
|
||||
#define ISP5_IRQ_IPIPE_INT_REG BIT(4)
|
||||
#define ISP5_IRQ_ISIF_INT(i) BIT(i)
|
||||
|
||||
#define ISP5_CTRL (0x006c)
|
||||
#define ISP5_CTRL_MSTANDBY BIT(24)
|
||||
#define ISP5_CTRL_VD_PULSE_EXT BIT(23)
|
||||
#define ISP5_CTRL_MSTANDBY_WAIT BIT(20)
|
||||
#define ISP5_CTRL_BL_CLK_ENABLE BIT(15)
|
||||
#define ISP5_CTRL_ISIF_CLK_ENABLE BIT(14)
|
||||
#define ISP5_CTRL_H3A_CLK_ENABLE BIT(13)
|
||||
#define ISP5_CTRL_RSZ_CLK_ENABLE BIT(12)
|
||||
#define ISP5_CTRL_IPIPE_CLK_ENABLE BIT(11)
|
||||
#define ISP5_CTRL_IPIPEIF_CLK_ENABLE BIT(10)
|
||||
#define ISP5_CTRL_SYNC_ENABLE BIT(9)
|
||||
#define ISP5_CTRL_PSYNC_CLK_SEL BIT(8)
|
||||
|
||||
/* ISS ISP ISIF register offsets */
|
||||
#define ISIF_SYNCEN (0x0000)
|
||||
#define ISIF_SYNCEN_DWEN BIT(1)
|
||||
#define ISIF_SYNCEN_SYEN BIT(0)
|
||||
|
||||
#define ISIF_MODESET (0x0004)
|
||||
#define ISIF_MODESET_INPMOD_MASK (3 << 12)
|
||||
#define ISIF_MODESET_INPMOD_RAW (0 << 12)
|
||||
#define ISIF_MODESET_INPMOD_YCBCR16 (1 << 12)
|
||||
#define ISIF_MODESET_INPMOD_YCBCR8 (2 << 12)
|
||||
#define ISIF_MODESET_CCDW_MASK (7 << 8)
|
||||
#define ISIF_MODESET_CCDW_2BIT (2 << 8)
|
||||
#define ISIF_MODESET_CCDMD (1 << 7)
|
||||
#define ISIF_MODESET_SWEN (1 << 5)
|
||||
#define ISIF_MODESET_HDPOL (1 << 3)
|
||||
#define ISIF_MODESET_VDPOL (1 << 2)
|
||||
|
||||
#define ISIF_SPH (0x0018)
|
||||
#define ISIF_SPH_MASK (0x7fff)
|
||||
|
||||
#define ISIF_LNH (0x001c)
|
||||
#define ISIF_LNH_MASK (0x7fff)
|
||||
|
||||
#define ISIF_LNV (0x0028)
|
||||
#define ISIF_LNV_MASK (0x7fff)
|
||||
|
||||
#define ISIF_HSIZE (0x0034)
|
||||
#define ISIF_HSIZE_ADCR BIT(12)
|
||||
#define ISIF_HSIZE_HSIZE_MASK (0xfff)
|
||||
|
||||
#define ISIF_CADU (0x003c)
|
||||
#define ISIF_CADU_MASK (0x7ff)
|
||||
|
||||
#define ISIF_CADL (0x0040)
|
||||
#define ISIF_CADL_MASK (0xffff)
|
||||
|
||||
#define ISIF_CCOLP (0x004c)
|
||||
#define ISIF_CCOLP_CP0_F0_R (0 << 6)
|
||||
#define ISIF_CCOLP_CP0_F0_GR (1 << 6)
|
||||
#define ISIF_CCOLP_CP0_F0_B (3 << 6)
|
||||
#define ISIF_CCOLP_CP0_F0_GB (2 << 6)
|
||||
#define ISIF_CCOLP_CP1_F0_R (0 << 4)
|
||||
#define ISIF_CCOLP_CP1_F0_GR (1 << 4)
|
||||
#define ISIF_CCOLP_CP1_F0_B (3 << 4)
|
||||
#define ISIF_CCOLP_CP1_F0_GB (2 << 4)
|
||||
#define ISIF_CCOLP_CP2_F0_R (0 << 2)
|
||||
#define ISIF_CCOLP_CP2_F0_GR (1 << 2)
|
||||
#define ISIF_CCOLP_CP2_F0_B (3 << 2)
|
||||
#define ISIF_CCOLP_CP2_F0_GB (2 << 2)
|
||||
#define ISIF_CCOLP_CP3_F0_R (0 << 0)
|
||||
#define ISIF_CCOLP_CP3_F0_GR (1 << 0)
|
||||
#define ISIF_CCOLP_CP3_F0_B (3 << 0)
|
||||
#define ISIF_CCOLP_CP3_F0_GB (2 << 0)
|
||||
|
||||
#define ISIF_VDINT(i) (0x0070 + (i) * 4)
|
||||
#define ISIF_VDINT_MASK (0x7fff)
|
||||
|
||||
#define ISIF_CGAMMAWD (0x0080)
|
||||
#define ISIF_CGAMMAWD_GWDI_MASK (0xf << 1)
|
||||
#define ISIF_CGAMMAWD_GWDI(bpp) ((16 - (bpp)) << 1)
|
||||
|
||||
#define ISIF_CCDCFG (0x0088)
|
||||
#define ISIF_CCDCFG_Y8POS BIT(11)
|
||||
|
||||
/* ISS ISP IPIPEIF register offsets */
|
||||
#define IPIPEIF_ENABLE (0x0000)
|
||||
|
||||
#define IPIPEIF_CFG1 (0x0004)
|
||||
#define IPIPEIF_CFG1_INPSRC1_MASK (3 << 14)
|
||||
#define IPIPEIF_CFG1_INPSRC1_VPORT_RAW (0 << 14)
|
||||
#define IPIPEIF_CFG1_INPSRC1_SDRAM_RAW (1 << 14)
|
||||
#define IPIPEIF_CFG1_INPSRC1_ISIF_DARKFM (2 << 14)
|
||||
#define IPIPEIF_CFG1_INPSRC1_SDRAM_YUV (3 << 14)
|
||||
#define IPIPEIF_CFG1_INPSRC2_MASK (3 << 2)
|
||||
#define IPIPEIF_CFG1_INPSRC2_ISIF (0 << 2)
|
||||
#define IPIPEIF_CFG1_INPSRC2_SDRAM_RAW (1 << 2)
|
||||
#define IPIPEIF_CFG1_INPSRC2_ISIF_DARKFM (2 << 2)
|
||||
#define IPIPEIF_CFG1_INPSRC2_SDRAM_YUV (3 << 2)
|
||||
|
||||
#define IPIPEIF_CFG2 (0x0030)
|
||||
#define IPIPEIF_CFG2_YUV8P BIT(7)
|
||||
#define IPIPEIF_CFG2_YUV8 BIT(6)
|
||||
#define IPIPEIF_CFG2_YUV16 BIT(3)
|
||||
#define IPIPEIF_CFG2_VDPOL BIT(2)
|
||||
#define IPIPEIF_CFG2_HDPOL BIT(1)
|
||||
#define IPIPEIF_CFG2_INTSW BIT(0)
|
||||
|
||||
#define IPIPEIF_CLKDIV (0x0040)
|
||||
|
||||
/* ISS ISP IPIPE register offsets */
|
||||
#define IPIPE_SRC_EN (0x0000)
|
||||
#define IPIPE_SRC_EN_EN BIT(0)
|
||||
|
||||
#define IPIPE_SRC_MODE (0x0004)
|
||||
#define IPIPE_SRC_MODE_WRT BIT(1)
|
||||
#define IPIPE_SRC_MODE_OST BIT(0)
|
||||
|
||||
#define IPIPE_SRC_FMT (0x0008)
|
||||
#define IPIPE_SRC_FMT_RAW2YUV (0 << 0)
|
||||
#define IPIPE_SRC_FMT_RAW2RAW (1 << 0)
|
||||
#define IPIPE_SRC_FMT_RAW2STATS (2 << 0)
|
||||
#define IPIPE_SRC_FMT_YUV2YUV (3 << 0)
|
||||
|
||||
#define IPIPE_SRC_COL (0x000c)
|
||||
#define IPIPE_SRC_COL_OO_R (0 << 6)
|
||||
#define IPIPE_SRC_COL_OO_GR (1 << 6)
|
||||
#define IPIPE_SRC_COL_OO_B (3 << 6)
|
||||
#define IPIPE_SRC_COL_OO_GB (2 << 6)
|
||||
#define IPIPE_SRC_COL_OE_R (0 << 4)
|
||||
#define IPIPE_SRC_COL_OE_GR (1 << 4)
|
||||
#define IPIPE_SRC_COL_OE_B (3 << 4)
|
||||
#define IPIPE_SRC_COL_OE_GB (2 << 4)
|
||||
#define IPIPE_SRC_COL_EO_R (0 << 2)
|
||||
#define IPIPE_SRC_COL_EO_GR (1 << 2)
|
||||
#define IPIPE_SRC_COL_EO_B (3 << 2)
|
||||
#define IPIPE_SRC_COL_EO_GB (2 << 2)
|
||||
#define IPIPE_SRC_COL_EE_R (0 << 0)
|
||||
#define IPIPE_SRC_COL_EE_GR (1 << 0)
|
||||
#define IPIPE_SRC_COL_EE_B (3 << 0)
|
||||
#define IPIPE_SRC_COL_EE_GB (2 << 0)
|
||||
|
||||
#define IPIPE_SRC_VPS (0x0010)
|
||||
#define IPIPE_SRC_VPS_MASK (0xffff)
|
||||
|
||||
#define IPIPE_SRC_VSZ (0x0014)
|
||||
#define IPIPE_SRC_VSZ_MASK (0x1fff)
|
||||
|
||||
#define IPIPE_SRC_HPS (0x0018)
|
||||
#define IPIPE_SRC_HPS_MASK (0xffff)
|
||||
|
||||
#define IPIPE_SRC_HSZ (0x001c)
|
||||
#define IPIPE_SRC_HSZ_MASK (0x1ffe)
|
||||
|
||||
#define IPIPE_SEL_SBU (0x0020)
|
||||
|
||||
#define IPIPE_SRC_STA (0x0024)
|
||||
|
||||
#define IPIPE_GCK_MMR (0x0028)
|
||||
#define IPIPE_GCK_MMR_REG BIT(0)
|
||||
|
||||
#define IPIPE_GCK_PIX (0x002c)
|
||||
#define IPIPE_GCK_PIX_G3 BIT(3)
|
||||
#define IPIPE_GCK_PIX_G2 BIT(2)
|
||||
#define IPIPE_GCK_PIX_G1 BIT(1)
|
||||
#define IPIPE_GCK_PIX_G0 BIT(0)
|
||||
|
||||
#define IPIPE_DPC_LUT_EN (0x0034)
|
||||
#define IPIPE_DPC_LUT_SEL (0x0038)
|
||||
#define IPIPE_DPC_LUT_ADR (0x003c)
|
||||
#define IPIPE_DPC_LUT_SIZ (0x0040)
|
||||
|
||||
#define IPIPE_DPC_OTF_EN (0x0044)
|
||||
#define IPIPE_DPC_OTF_TYP (0x0048)
|
||||
#define IPIPE_DPC_OTF_2_D_THR_R (0x004c)
|
||||
#define IPIPE_DPC_OTF_2_D_THR_GR (0x0050)
|
||||
#define IPIPE_DPC_OTF_2_D_THR_GB (0x0054)
|
||||
#define IPIPE_DPC_OTF_2_D_THR_B (0x0058)
|
||||
#define IPIPE_DPC_OTF_2_C_THR_R (0x005c)
|
||||
#define IPIPE_DPC_OTF_2_C_THR_GR (0x0060)
|
||||
#define IPIPE_DPC_OTF_2_C_THR_GB (0x0064)
|
||||
#define IPIPE_DPC_OTF_2_C_THR_B (0x0068)
|
||||
#define IPIPE_DPC_OTF_3_SHF (0x006c)
|
||||
#define IPIPE_DPC_OTF_3_D_THR (0x0070)
|
||||
#define IPIPE_DPC_OTF_3_D_SPL (0x0074)
|
||||
#define IPIPE_DPC_OTF_3_D_MIN (0x0078)
|
||||
#define IPIPE_DPC_OTF_3_D_MAX (0x007c)
|
||||
#define IPIPE_DPC_OTF_3_C_THR (0x0080)
|
||||
#define IPIPE_DPC_OTF_3_C_SLP (0x0084)
|
||||
#define IPIPE_DPC_OTF_3_C_MIN (0x0088)
|
||||
#define IPIPE_DPC_OTF_3_C_MAX (0x008c)
|
||||
|
||||
#define IPIPE_LSC_VOFT (0x0090)
|
||||
#define IPIPE_LSC_VA2 (0x0094)
|
||||
#define IPIPE_LSC_VA1 (0x0098)
|
||||
#define IPIPE_LSC_VS (0x009c)
|
||||
#define IPIPE_LSC_HOFT (0x00a0)
|
||||
#define IPIPE_LSC_HA2 (0x00a4)
|
||||
#define IPIPE_LSC_HA1 (0x00a8)
|
||||
#define IPIPE_LSC_HS (0x00ac)
|
||||
#define IPIPE_LSC_GAN_R (0x00b0)
|
||||
#define IPIPE_LSC_GAN_GR (0x00b4)
|
||||
#define IPIPE_LSC_GAN_GB (0x00b8)
|
||||
#define IPIPE_LSC_GAN_B (0x00bc)
|
||||
#define IPIPE_LSC_OFT_R (0x00c0)
|
||||
#define IPIPE_LSC_OFT_GR (0x00c4)
|
||||
#define IPIPE_LSC_OFT_GB (0x00c8)
|
||||
#define IPIPE_LSC_OFT_B (0x00cc)
|
||||
#define IPIPE_LSC_SHF (0x00d0)
|
||||
#define IPIPE_LSC_MAX (0x00d4)
|
||||
|
||||
#define IPIPE_D2F_1ST_EN (0x00d8)
|
||||
#define IPIPE_D2F_1ST_TYP (0x00dc)
|
||||
#define IPIPE_D2F_1ST_THR_00 (0x00e0)
|
||||
#define IPIPE_D2F_1ST_THR_01 (0x00e4)
|
||||
#define IPIPE_D2F_1ST_THR_02 (0x00e8)
|
||||
#define IPIPE_D2F_1ST_THR_03 (0x00ec)
|
||||
#define IPIPE_D2F_1ST_THR_04 (0x00f0)
|
||||
#define IPIPE_D2F_1ST_THR_05 (0x00f4)
|
||||
#define IPIPE_D2F_1ST_THR_06 (0x00f8)
|
||||
#define IPIPE_D2F_1ST_THR_07 (0x00fc)
|
||||
#define IPIPE_D2F_1ST_STR_00 (0x0100)
|
||||
#define IPIPE_D2F_1ST_STR_01 (0x0104)
|
||||
#define IPIPE_D2F_1ST_STR_02 (0x0108)
|
||||
#define IPIPE_D2F_1ST_STR_03 (0x010c)
|
||||
#define IPIPE_D2F_1ST_STR_04 (0x0110)
|
||||
#define IPIPE_D2F_1ST_STR_05 (0x0114)
|
||||
#define IPIPE_D2F_1ST_STR_06 (0x0118)
|
||||
#define IPIPE_D2F_1ST_STR_07 (0x011c)
|
||||
#define IPIPE_D2F_1ST_SPR_00 (0x0120)
|
||||
#define IPIPE_D2F_1ST_SPR_01 (0x0124)
|
||||
#define IPIPE_D2F_1ST_SPR_02 (0x0128)
|
||||
#define IPIPE_D2F_1ST_SPR_03 (0x012c)
|
||||
#define IPIPE_D2F_1ST_SPR_04 (0x0130)
|
||||
#define IPIPE_D2F_1ST_SPR_05 (0x0134)
|
||||
#define IPIPE_D2F_1ST_SPR_06 (0x0138)
|
||||
#define IPIPE_D2F_1ST_SPR_07 (0x013c)
|
||||
#define IPIPE_D2F_1ST_EDG_MIN (0x0140)
|
||||
#define IPIPE_D2F_1ST_EDG_MAX (0x0144)
|
||||
#define IPIPE_D2F_2ND_EN (0x0148)
|
||||
#define IPIPE_D2F_2ND_TYP (0x014c)
|
||||
#define IPIPE_D2F_2ND_THR00 (0x0150)
|
||||
#define IPIPE_D2F_2ND_THR01 (0x0154)
|
||||
#define IPIPE_D2F_2ND_THR02 (0x0158)
|
||||
#define IPIPE_D2F_2ND_THR03 (0x015c)
|
||||
#define IPIPE_D2F_2ND_THR04 (0x0160)
|
||||
#define IPIPE_D2F_2ND_THR05 (0x0164)
|
||||
#define IPIPE_D2F_2ND_THR06 (0x0168)
|
||||
#define IPIPE_D2F_2ND_THR07 (0x016c)
|
||||
#define IPIPE_D2F_2ND_STR_00 (0x0170)
|
||||
#define IPIPE_D2F_2ND_STR_01 (0x0174)
|
||||
#define IPIPE_D2F_2ND_STR_02 (0x0178)
|
||||
#define IPIPE_D2F_2ND_STR_03 (0x017c)
|
||||
#define IPIPE_D2F_2ND_STR_04 (0x0180)
|
||||
#define IPIPE_D2F_2ND_STR_05 (0x0184)
|
||||
#define IPIPE_D2F_2ND_STR_06 (0x0188)
|
||||
#define IPIPE_D2F_2ND_STR_07 (0x018c)
|
||||
#define IPIPE_D2F_2ND_SPR_00 (0x0190)
|
||||
#define IPIPE_D2F_2ND_SPR_01 (0x0194)
|
||||
#define IPIPE_D2F_2ND_SPR_02 (0x0198)
|
||||
#define IPIPE_D2F_2ND_SPR_03 (0x019c)
|
||||
#define IPIPE_D2F_2ND_SPR_04 (0x01a0)
|
||||
#define IPIPE_D2F_2ND_SPR_05 (0x01a4)
|
||||
#define IPIPE_D2F_2ND_SPR_06 (0x01a8)
|
||||
#define IPIPE_D2F_2ND_SPR_07 (0x01ac)
|
||||
#define IPIPE_D2F_2ND_EDG_MIN (0x01b0)
|
||||
#define IPIPE_D2F_2ND_EDG_MAX (0x01b4)
|
||||
|
||||
#define IPIPE_GIC_EN (0x01b8)
|
||||
#define IPIPE_GIC_TYP (0x01bc)
|
||||
#define IPIPE_GIC_GAN (0x01c0)
|
||||
#define IPIPE_GIC_NFGAIN (0x01c4)
|
||||
#define IPIPE_GIC_THR (0x01c8)
|
||||
#define IPIPE_GIC_SLP (0x01cc)
|
||||
|
||||
#define IPIPE_WB2_OFT_R (0x01d0)
|
||||
#define IPIPE_WB2_OFT_GR (0x01d4)
|
||||
#define IPIPE_WB2_OFT_GB (0x01d8)
|
||||
#define IPIPE_WB2_OFT_B (0x01dc)
|
||||
|
||||
#define IPIPE_WB2_WGN_R (0x01e0)
|
||||
#define IPIPE_WB2_WGN_GR (0x01e4)
|
||||
#define IPIPE_WB2_WGN_GB (0x01e8)
|
||||
#define IPIPE_WB2_WGN_B (0x01ec)
|
||||
|
||||
#define IPIPE_CFA_MODE (0x01f0)
|
||||
#define IPIPE_CFA_2DIR_HPF_THR (0x01f4)
|
||||
#define IPIPE_CFA_2DIR_HPF_SLP (0x01f8)
|
||||
#define IPIPE_CFA_2DIR_MIX_THR (0x01fc)
|
||||
#define IPIPE_CFA_2DIR_MIX_SLP (0x0200)
|
||||
#define IPIPE_CFA_2DIR_DIR_TRH (0x0204)
|
||||
#define IPIPE_CFA_2DIR_DIR_SLP (0x0208)
|
||||
#define IPIPE_CFA_2DIR_NDWT (0x020c)
|
||||
#define IPIPE_CFA_MONO_HUE_FRA (0x0210)
|
||||
#define IPIPE_CFA_MONO_EDG_THR (0x0214)
|
||||
#define IPIPE_CFA_MONO_THR_MIN (0x0218)
|
||||
|
||||
#define IPIPE_CFA_MONO_THR_SLP (0x021c)
|
||||
#define IPIPE_CFA_MONO_SLP_MIN (0x0220)
|
||||
#define IPIPE_CFA_MONO_SLP_SLP (0x0224)
|
||||
#define IPIPE_CFA_MONO_LPWT (0x0228)
|
||||
|
||||
#define IPIPE_RGB1_MUL_RR (0x022c)
|
||||
#define IPIPE_RGB1_MUL_GR (0x0230)
|
||||
#define IPIPE_RGB1_MUL_BR (0x0234)
|
||||
#define IPIPE_RGB1_MUL_RG (0x0238)
|
||||
#define IPIPE_RGB1_MUL_GG (0x023c)
|
||||
#define IPIPE_RGB1_MUL_BG (0x0240)
|
||||
#define IPIPE_RGB1_MUL_RB (0x0244)
|
||||
#define IPIPE_RGB1_MUL_GB (0x0248)
|
||||
#define IPIPE_RGB1_MUL_BB (0x024c)
|
||||
#define IPIPE_RGB1_OFT_OR (0x0250)
|
||||
#define IPIPE_RGB1_OFT_OG (0x0254)
|
||||
#define IPIPE_RGB1_OFT_OB (0x0258)
|
||||
#define IPIPE_GMM_CFG (0x025c)
|
||||
#define IPIPE_RGB2_MUL_RR (0x0260)
|
||||
#define IPIPE_RGB2_MUL_GR (0x0264)
|
||||
#define IPIPE_RGB2_MUL_BR (0x0268)
|
||||
#define IPIPE_RGB2_MUL_RG (0x026c)
|
||||
#define IPIPE_RGB2_MUL_GG (0x0270)
|
||||
#define IPIPE_RGB2_MUL_BG (0x0274)
|
||||
#define IPIPE_RGB2_MUL_RB (0x0278)
|
||||
#define IPIPE_RGB2_MUL_GB (0x027c)
|
||||
#define IPIPE_RGB2_MUL_BB (0x0280)
|
||||
#define IPIPE_RGB2_OFT_OR (0x0284)
|
||||
#define IPIPE_RGB2_OFT_OG (0x0288)
|
||||
#define IPIPE_RGB2_OFT_OB (0x028c)
|
||||
|
||||
#define IPIPE_YUV_ADJ (0x0294)
|
||||
#define IPIPE_YUV_MUL_RY (0x0298)
|
||||
#define IPIPE_YUV_MUL_GY (0x029c)
|
||||
#define IPIPE_YUV_MUL_BY (0x02a0)
|
||||
#define IPIPE_YUV_MUL_RCB (0x02a4)
|
||||
#define IPIPE_YUV_MUL_GCB (0x02a8)
|
||||
#define IPIPE_YUV_MUL_BCB (0x02ac)
|
||||
#define IPIPE_YUV_MUL_RCR (0x02b0)
|
||||
#define IPIPE_YUV_MUL_GCR (0x02b4)
|
||||
#define IPIPE_YUV_MUL_BCR (0x02b8)
|
||||
#define IPIPE_YUV_OFT_Y (0x02bc)
|
||||
#define IPIPE_YUV_OFT_CB (0x02c0)
|
||||
#define IPIPE_YUV_OFT_CR (0x02c4)
|
||||
|
||||
#define IPIPE_YUV_PHS (0x02c8)
|
||||
#define IPIPE_YUV_PHS_LPF BIT(1)
|
||||
#define IPIPE_YUV_PHS_POS BIT(0)
|
||||
|
||||
#define IPIPE_YEE_EN (0x02d4)
|
||||
#define IPIPE_YEE_TYP (0x02d8)
|
||||
#define IPIPE_YEE_SHF (0x02dc)
|
||||
#define IPIPE_YEE_MUL_00 (0x02e0)
|
||||
#define IPIPE_YEE_MUL_01 (0x02e4)
|
||||
#define IPIPE_YEE_MUL_02 (0x02e8)
|
||||
#define IPIPE_YEE_MUL_10 (0x02ec)
|
||||
#define IPIPE_YEE_MUL_11 (0x02f0)
|
||||
#define IPIPE_YEE_MUL_12 (0x02f4)
|
||||
#define IPIPE_YEE_MUL_20 (0x02f8)
|
||||
#define IPIPE_YEE_MUL_21 (0x02fc)
|
||||
#define IPIPE_YEE_MUL_22 (0x0300)
|
||||
#define IPIPE_YEE_THR (0x0304)
|
||||
#define IPIPE_YEE_E_GAN (0x0308)
|
||||
#define IPIPE_YEE_E_THR_1 (0x030c)
|
||||
#define IPIPE_YEE_E_THR_2 (0x0310)
|
||||
#define IPIPE_YEE_G_GAN (0x0314)
|
||||
#define IPIPE_YEE_G_OFT (0x0318)
|
||||
|
||||
#define IPIPE_CAR_EN (0x031c)
|
||||
#define IPIPE_CAR_TYP (0x0320)
|
||||
#define IPIPE_CAR_SW (0x0324)
|
||||
#define IPIPE_CAR_HPF_TYP (0x0328)
|
||||
#define IPIPE_CAR_HPF_SHF (0x032c)
|
||||
#define IPIPE_CAR_HPF_THR (0x0330)
|
||||
#define IPIPE_CAR_GN1_GAN (0x0334)
|
||||
#define IPIPE_CAR_GN1_SHF (0x0338)
|
||||
#define IPIPE_CAR_GN1_MIN (0x033c)
|
||||
#define IPIPE_CAR_GN2_GAN (0x0340)
|
||||
#define IPIPE_CAR_GN2_SHF (0x0344)
|
||||
#define IPIPE_CAR_GN2_MIN (0x0348)
|
||||
#define IPIPE_CGS_EN (0x034c)
|
||||
#define IPIPE_CGS_GN1_L_THR (0x0350)
|
||||
#define IPIPE_CGS_GN1_L_GAIN (0x0354)
|
||||
#define IPIPE_CGS_GN1_L_SHF (0x0358)
|
||||
#define IPIPE_CGS_GN1_L_MIN (0x035c)
|
||||
#define IPIPE_CGS_GN1_H_THR (0x0360)
|
||||
#define IPIPE_CGS_GN1_H_GAIN (0x0364)
|
||||
#define IPIPE_CGS_GN1_H_SHF (0x0368)
|
||||
#define IPIPE_CGS_GN1_H_MIN (0x036c)
|
||||
#define IPIPE_CGS_GN2_L_THR (0x0370)
|
||||
#define IPIPE_CGS_GN2_L_GAIN (0x0374)
|
||||
#define IPIPE_CGS_GN2_L_SHF (0x0378)
|
||||
#define IPIPE_CGS_GN2_L_MIN (0x037c)
|
||||
|
||||
#define IPIPE_BOX_EN (0x0380)
|
||||
#define IPIPE_BOX_MODE (0x0384)
|
||||
#define IPIPE_BOX_TYP (0x0388)
|
||||
#define IPIPE_BOX_SHF (0x038c)
|
||||
#define IPIPE_BOX_SDR_SAD_H (0x0390)
|
||||
#define IPIPE_BOX_SDR_SAD_L (0x0394)
|
||||
|
||||
#define IPIPE_HST_EN (0x039c)
|
||||
#define IPIPE_HST_MODE (0x03a0)
|
||||
#define IPIPE_HST_SEL (0x03a4)
|
||||
#define IPIPE_HST_PARA (0x03a8)
|
||||
#define IPIPE_HST_0_VPS (0x03ac)
|
||||
#define IPIPE_HST_0_VSZ (0x03b0)
|
||||
#define IPIPE_HST_0_HPS (0x03b4)
|
||||
#define IPIPE_HST_0_HSZ (0x03b8)
|
||||
#define IPIPE_HST_1_VPS (0x03bc)
|
||||
#define IPIPE_HST_1_VSZ (0x03c0)
|
||||
#define IPIPE_HST_1_HPS (0x03c4)
|
||||
#define IPIPE_HST_1_HSZ (0x03c8)
|
||||
#define IPIPE_HST_2_VPS (0x03cc)
|
||||
#define IPIPE_HST_2_VSZ (0x03d0)
|
||||
#define IPIPE_HST_2_HPS (0x03d4)
|
||||
#define IPIPE_HST_2_HSZ (0x03d8)
|
||||
#define IPIPE_HST_3_VPS (0x03dc)
|
||||
#define IPIPE_HST_3_VSZ (0x03e0)
|
||||
#define IPIPE_HST_3_HPS (0x03e4)
|
||||
#define IPIPE_HST_3_HSZ (0x03e8)
|
||||
#define IPIPE_HST_TBL (0x03ec)
|
||||
#define IPIPE_HST_MUL_R (0x03f0)
|
||||
#define IPIPE_HST_MUL_GR (0x03f4)
|
||||
#define IPIPE_HST_MUL_GB (0x03f8)
|
||||
#define IPIPE_HST_MUL_B (0x03fc)
|
||||
|
||||
#define IPIPE_BSC_EN (0x0400)
|
||||
#define IPIPE_BSC_MODE (0x0404)
|
||||
#define IPIPE_BSC_TYP (0x0408)
|
||||
#define IPIPE_BSC_ROW_VCT (0x040c)
|
||||
#define IPIPE_BSC_ROW_SHF (0x0410)
|
||||
#define IPIPE_BSC_ROW_VPO (0x0414)
|
||||
#define IPIPE_BSC_ROW_VNU (0x0418)
|
||||
#define IPIPE_BSC_ROW_VSKIP (0x041c)
|
||||
#define IPIPE_BSC_ROW_HPO (0x0420)
|
||||
#define IPIPE_BSC_ROW_HNU (0x0424)
|
||||
#define IPIPE_BSC_ROW_HSKIP (0x0428)
|
||||
#define IPIPE_BSC_COL_VCT (0x042c)
|
||||
#define IPIPE_BSC_COL_SHF (0x0430)
|
||||
#define IPIPE_BSC_COL_VPO (0x0434)
|
||||
#define IPIPE_BSC_COL_VNU (0x0438)
|
||||
#define IPIPE_BSC_COL_VSKIP (0x043c)
|
||||
#define IPIPE_BSC_COL_HPO (0x0440)
|
||||
#define IPIPE_BSC_COL_HNU (0x0444)
|
||||
#define IPIPE_BSC_COL_HSKIP (0x0448)
|
||||
|
||||
#define IPIPE_BSC_EN (0x0400)
|
||||
|
||||
/* ISS ISP Resizer register offsets */
|
||||
#define RSZ_REVISION (0x0000)
|
||||
#define RSZ_SYSCONFIG (0x0004)
|
||||
#define RSZ_SYSCONFIG_RSZB_CLK_EN BIT(9)
|
||||
#define RSZ_SYSCONFIG_RSZA_CLK_EN BIT(8)
|
||||
|
||||
#define RSZ_IN_FIFO_CTRL (0x000c)
|
||||
#define RSZ_IN_FIFO_CTRL_THRLD_LOW_MASK (0x1ff << 16)
|
||||
#define RSZ_IN_FIFO_CTRL_THRLD_LOW_SHIFT 16
|
||||
#define RSZ_IN_FIFO_CTRL_THRLD_HIGH_MASK (0x1ff << 0)
|
||||
#define RSZ_IN_FIFO_CTRL_THRLD_HIGH_SHIFT 0
|
||||
|
||||
#define RSZ_FRACDIV (0x0008)
|
||||
#define RSZ_FRACDIV_MASK (0xffff)
|
||||
|
||||
#define RSZ_SRC_EN (0x0020)
|
||||
#define RSZ_SRC_EN_SRC_EN BIT(0)
|
||||
|
||||
#define RSZ_SRC_MODE (0x0024)
|
||||
#define RSZ_SRC_MODE_OST BIT(0)
|
||||
#define RSZ_SRC_MODE_WRT BIT(1)
|
||||
|
||||
#define RSZ_SRC_FMT0 (0x0028)
|
||||
#define RSZ_SRC_FMT0_BYPASS BIT(1)
|
||||
#define RSZ_SRC_FMT0_SEL BIT(0)
|
||||
|
||||
#define RSZ_SRC_FMT1 (0x002c)
|
||||
#define RSZ_SRC_FMT1_IN420 BIT(1)
|
||||
|
||||
#define RSZ_SRC_VPS (0x0030)
|
||||
#define RSZ_SRC_VSZ (0x0034)
|
||||
#define RSZ_SRC_HPS (0x0038)
|
||||
#define RSZ_SRC_HSZ (0x003c)
|
||||
#define RSZ_DMA_RZA (0x0040)
|
||||
#define RSZ_DMA_RZB (0x0044)
|
||||
#define RSZ_DMA_STA (0x0048)
|
||||
#define RSZ_GCK_MMR (0x004c)
|
||||
#define RSZ_GCK_MMR_MMR BIT(0)
|
||||
|
||||
#define RSZ_GCK_SDR (0x0054)
|
||||
#define RSZ_GCK_SDR_CORE BIT(0)
|
||||
|
||||
#define RSZ_IRQ_RZA (0x0058)
|
||||
#define RSZ_IRQ_RZA_MASK (0x1fff)
|
||||
|
||||
#define RSZ_IRQ_RZB (0x005c)
|
||||
#define RSZ_IRQ_RZB_MASK (0x1fff)
|
||||
|
||||
#define RSZ_YUV_Y_MIN (0x0060)
|
||||
#define RSZ_YUV_Y_MAX (0x0064)
|
||||
#define RSZ_YUV_C_MIN (0x0068)
|
||||
#define RSZ_YUV_C_MAX (0x006c)
|
||||
|
||||
#define RSZ_SEQ (0x0074)
|
||||
#define RSZ_SEQ_HRVB BIT(2)
|
||||
#define RSZ_SEQ_HRVA BIT(0)
|
||||
|
||||
#define RZA_EN (0x0078)
|
||||
#define RZA_MODE (0x007c)
|
||||
#define RZA_MODE_ONE_SHOT BIT(0)
|
||||
|
||||
#define RZA_420 (0x0080)
|
||||
#define RZA_I_VPS (0x0084)
|
||||
#define RZA_I_HPS (0x0088)
|
||||
#define RZA_O_VSZ (0x008c)
|
||||
#define RZA_O_HSZ (0x0090)
|
||||
#define RZA_V_PHS_Y (0x0094)
|
||||
#define RZA_V_PHS_C (0x0098)
|
||||
#define RZA_V_DIF (0x009c)
|
||||
#define RZA_V_TYP (0x00a0)
|
||||
#define RZA_V_LPF (0x00a4)
|
||||
#define RZA_H_PHS (0x00a8)
|
||||
#define RZA_H_DIF (0x00b0)
|
||||
#define RZA_H_TYP (0x00b4)
|
||||
#define RZA_H_LPF (0x00b8)
|
||||
#define RZA_DWN_EN (0x00bc)
|
||||
#define RZA_SDR_Y_BAD_H (0x00d0)
|
||||
#define RZA_SDR_Y_BAD_L (0x00d4)
|
||||
#define RZA_SDR_Y_SAD_H (0x00d8)
|
||||
#define RZA_SDR_Y_SAD_L (0x00dc)
|
||||
#define RZA_SDR_Y_OFT (0x00e0)
|
||||
#define RZA_SDR_Y_PTR_S (0x00e4)
|
||||
#define RZA_SDR_Y_PTR_E (0x00e8)
|
||||
#define RZA_SDR_C_BAD_H (0x00ec)
|
||||
#define RZA_SDR_C_BAD_L (0x00f0)
|
||||
#define RZA_SDR_C_SAD_H (0x00f4)
|
||||
#define RZA_SDR_C_SAD_L (0x00f8)
|
||||
#define RZA_SDR_C_OFT (0x00fc)
|
||||
#define RZA_SDR_C_PTR_S (0x0100)
|
||||
#define RZA_SDR_C_PTR_E (0x0104)
|
||||
|
||||
#define RZB_EN (0x0108)
|
||||
#define RZB_MODE (0x010c)
|
||||
#define RZB_420 (0x0110)
|
||||
#define RZB_I_VPS (0x0114)
|
||||
#define RZB_I_HPS (0x0118)
|
||||
#define RZB_O_VSZ (0x011c)
|
||||
#define RZB_O_HSZ (0x0120)
|
||||
|
||||
#define RZB_V_DIF (0x012c)
|
||||
#define RZB_V_TYP (0x0130)
|
||||
#define RZB_V_LPF (0x0134)
|
||||
|
||||
#define RZB_H_DIF (0x0140)
|
||||
#define RZB_H_TYP (0x0144)
|
||||
#define RZB_H_LPF (0x0148)
|
||||
|
||||
#define RZB_SDR_Y_BAD_H (0x0160)
|
||||
#define RZB_SDR_Y_BAD_L (0x0164)
|
||||
#define RZB_SDR_Y_SAD_H (0x0168)
|
||||
#define RZB_SDR_Y_SAD_L (0x016c)
|
||||
#define RZB_SDR_Y_OFT (0x0170)
|
||||
#define RZB_SDR_Y_PTR_S (0x0174)
|
||||
#define RZB_SDR_Y_PTR_E (0x0178)
|
||||
#define RZB_SDR_C_BAD_H (0x017c)
|
||||
#define RZB_SDR_C_BAD_L (0x0180)
|
||||
#define RZB_SDR_C_SAD_H (0x0184)
|
||||
#define RZB_SDR_C_SAD_L (0x0188)
|
||||
|
||||
#define RZB_SDR_C_PTR_S (0x0190)
|
||||
#define RZB_SDR_C_PTR_E (0x0194)
|
||||
|
||||
/* Shared Bitmasks between RZA & RZB */
|
||||
#define RSZ_EN_EN BIT(0)
|
||||
|
||||
#define RSZ_420_CEN BIT(1)
|
||||
#define RSZ_420_YEN BIT(0)
|
||||
|
||||
#define RSZ_I_VPS_MASK (0x1fff)
|
||||
|
||||
#define RSZ_I_HPS_MASK (0x1fff)
|
||||
|
||||
#define RSZ_O_VSZ_MASK (0x1fff)
|
||||
|
||||
#define RSZ_O_HSZ_MASK (0x1ffe)
|
||||
|
||||
#define RSZ_V_PHS_Y_MASK (0x3fff)
|
||||
|
||||
#define RSZ_V_PHS_C_MASK (0x3fff)
|
||||
|
||||
#define RSZ_V_DIF_MASK (0x3fff)
|
||||
|
||||
#define RSZ_V_TYP_C BIT(1)
|
||||
#define RSZ_V_TYP_Y BIT(0)
|
||||
|
||||
#define RSZ_V_LPF_C_MASK (0x3f << 6)
|
||||
#define RSZ_V_LPF_C_SHIFT 6
|
||||
#define RSZ_V_LPF_Y_MASK (0x3f << 0)
|
||||
#define RSZ_V_LPF_Y_SHIFT 0
|
||||
|
||||
#define RSZ_H_PHS_MASK (0x3fff)
|
||||
|
||||
#define RSZ_H_DIF_MASK (0x3fff)
|
||||
|
||||
#define RSZ_H_TYP_C BIT(1)
|
||||
#define RSZ_H_TYP_Y BIT(0)
|
||||
|
||||
#define RSZ_H_LPF_C_MASK (0x3f << 6)
|
||||
#define RSZ_H_LPF_C_SHIFT 6
|
||||
#define RSZ_H_LPF_Y_MASK (0x3f << 0)
|
||||
#define RSZ_H_LPF_Y_SHIFT 0
|
||||
|
||||
#define RSZ_DWN_EN_DWN_EN BIT(0)
|
||||
|
||||
#endif /* _OMAP4_ISS_REGS_H_ */
|
@ -1,884 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - ISP RESIZER module
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "iss.h"
|
||||
#include "iss_regs.h"
|
||||
#include "iss_resizer.h"
|
||||
|
||||
static const unsigned int resizer_fmts[] = {
|
||||
MEDIA_BUS_FMT_UYVY8_1X16,
|
||||
MEDIA_BUS_FMT_YUYV8_1X16,
|
||||
};
|
||||
|
||||
/*
|
||||
* resizer_print_status - Print current RESIZER Module register values.
|
||||
* @resizer: Pointer to ISS ISP RESIZER device.
|
||||
*
|
||||
* Also prints other debug information stored in the RESIZER module.
|
||||
*/
|
||||
#define RSZ_PRINT_REGISTER(iss, name)\
|
||||
dev_dbg(iss->dev, "###RSZ " #name "=0x%08x\n", \
|
||||
iss_reg_read(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_##name))
|
||||
|
||||
#define RZA_PRINT_REGISTER(iss, name)\
|
||||
dev_dbg(iss->dev, "###RZA " #name "=0x%08x\n", \
|
||||
iss_reg_read(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_##name))
|
||||
|
||||
static void resizer_print_status(struct iss_resizer_device *resizer)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(resizer);
|
||||
|
||||
dev_dbg(iss->dev, "-------------RESIZER Register dump-------------\n");
|
||||
|
||||
RSZ_PRINT_REGISTER(iss, SYSCONFIG);
|
||||
RSZ_PRINT_REGISTER(iss, IN_FIFO_CTRL);
|
||||
RSZ_PRINT_REGISTER(iss, FRACDIV);
|
||||
RSZ_PRINT_REGISTER(iss, SRC_EN);
|
||||
RSZ_PRINT_REGISTER(iss, SRC_MODE);
|
||||
RSZ_PRINT_REGISTER(iss, SRC_FMT0);
|
||||
RSZ_PRINT_REGISTER(iss, SRC_FMT1);
|
||||
RSZ_PRINT_REGISTER(iss, SRC_VPS);
|
||||
RSZ_PRINT_REGISTER(iss, SRC_VSZ);
|
||||
RSZ_PRINT_REGISTER(iss, SRC_HPS);
|
||||
RSZ_PRINT_REGISTER(iss, SRC_HSZ);
|
||||
RSZ_PRINT_REGISTER(iss, DMA_RZA);
|
||||
RSZ_PRINT_REGISTER(iss, DMA_RZB);
|
||||
RSZ_PRINT_REGISTER(iss, DMA_STA);
|
||||
RSZ_PRINT_REGISTER(iss, GCK_MMR);
|
||||
RSZ_PRINT_REGISTER(iss, GCK_SDR);
|
||||
RSZ_PRINT_REGISTER(iss, IRQ_RZA);
|
||||
RSZ_PRINT_REGISTER(iss, IRQ_RZB);
|
||||
RSZ_PRINT_REGISTER(iss, YUV_Y_MIN);
|
||||
RSZ_PRINT_REGISTER(iss, YUV_Y_MAX);
|
||||
RSZ_PRINT_REGISTER(iss, YUV_C_MIN);
|
||||
RSZ_PRINT_REGISTER(iss, YUV_C_MAX);
|
||||
RSZ_PRINT_REGISTER(iss, SEQ);
|
||||
|
||||
RZA_PRINT_REGISTER(iss, EN);
|
||||
RZA_PRINT_REGISTER(iss, MODE);
|
||||
RZA_PRINT_REGISTER(iss, 420);
|
||||
RZA_PRINT_REGISTER(iss, I_VPS);
|
||||
RZA_PRINT_REGISTER(iss, I_HPS);
|
||||
RZA_PRINT_REGISTER(iss, O_VSZ);
|
||||
RZA_PRINT_REGISTER(iss, O_HSZ);
|
||||
RZA_PRINT_REGISTER(iss, V_PHS_Y);
|
||||
RZA_PRINT_REGISTER(iss, V_PHS_C);
|
||||
RZA_PRINT_REGISTER(iss, V_DIF);
|
||||
RZA_PRINT_REGISTER(iss, V_TYP);
|
||||
RZA_PRINT_REGISTER(iss, V_LPF);
|
||||
RZA_PRINT_REGISTER(iss, H_PHS);
|
||||
RZA_PRINT_REGISTER(iss, H_DIF);
|
||||
RZA_PRINT_REGISTER(iss, H_TYP);
|
||||
RZA_PRINT_REGISTER(iss, H_LPF);
|
||||
RZA_PRINT_REGISTER(iss, DWN_EN);
|
||||
RZA_PRINT_REGISTER(iss, SDR_Y_BAD_H);
|
||||
RZA_PRINT_REGISTER(iss, SDR_Y_BAD_L);
|
||||
RZA_PRINT_REGISTER(iss, SDR_Y_SAD_H);
|
||||
RZA_PRINT_REGISTER(iss, SDR_Y_SAD_L);
|
||||
RZA_PRINT_REGISTER(iss, SDR_Y_OFT);
|
||||
RZA_PRINT_REGISTER(iss, SDR_Y_PTR_S);
|
||||
RZA_PRINT_REGISTER(iss, SDR_Y_PTR_E);
|
||||
RZA_PRINT_REGISTER(iss, SDR_C_BAD_H);
|
||||
RZA_PRINT_REGISTER(iss, SDR_C_BAD_L);
|
||||
RZA_PRINT_REGISTER(iss, SDR_C_SAD_H);
|
||||
RZA_PRINT_REGISTER(iss, SDR_C_SAD_L);
|
||||
RZA_PRINT_REGISTER(iss, SDR_C_OFT);
|
||||
RZA_PRINT_REGISTER(iss, SDR_C_PTR_S);
|
||||
RZA_PRINT_REGISTER(iss, SDR_C_PTR_E);
|
||||
|
||||
dev_dbg(iss->dev, "-----------------------------------------------\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* resizer_enable - Enable/Disable RESIZER.
|
||||
* @enable: enable flag
|
||||
*
|
||||
*/
|
||||
static void resizer_enable(struct iss_resizer_device *resizer, u8 enable)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(resizer);
|
||||
|
||||
iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_EN,
|
||||
RSZ_SRC_EN_SRC_EN, enable ? RSZ_SRC_EN_SRC_EN : 0);
|
||||
|
||||
/* TODO: Enable RSZB */
|
||||
iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_EN, RSZ_EN_EN,
|
||||
enable ? RSZ_EN_EN : 0);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Format- and pipeline-related configuration helpers
|
||||
*/
|
||||
|
||||
/*
|
||||
* resizer_set_outaddr - Set memory address to save output image
|
||||
* @resizer: Pointer to ISP RESIZER device.
|
||||
* @addr: 32-bit memory address aligned on 32 byte boundary.
|
||||
*
|
||||
* Sets the memory address where the output will be saved.
|
||||
*/
|
||||
static void resizer_set_outaddr(struct iss_resizer_device *resizer, u32 addr)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(resizer);
|
||||
struct v4l2_mbus_framefmt *informat, *outformat;
|
||||
|
||||
informat = &resizer->formats[RESIZER_PAD_SINK];
|
||||
outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM];
|
||||
|
||||
/* Save address split in Base Address H & L */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_BAD_H,
|
||||
(addr >> 16) & 0xffff);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_BAD_L,
|
||||
addr & 0xffff);
|
||||
|
||||
/* SAD = BAD */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_SAD_H,
|
||||
(addr >> 16) & 0xffff);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_SAD_L,
|
||||
addr & 0xffff);
|
||||
|
||||
/* Program UV buffer address... Hardcoded to be contiguous! */
|
||||
if ((informat->code == MEDIA_BUS_FMT_UYVY8_1X16) &&
|
||||
(outformat->code == MEDIA_BUS_FMT_YUYV8_1_5X8)) {
|
||||
u32 c_addr = addr + resizer->video_out.bpl_value
|
||||
* outformat->height;
|
||||
|
||||
/* Ensure Y_BAD_L[6:0] = C_BAD_L[6:0]*/
|
||||
if ((c_addr ^ addr) & 0x7f) {
|
||||
c_addr &= ~0x7f;
|
||||
c_addr += 0x80;
|
||||
c_addr |= addr & 0x7f;
|
||||
}
|
||||
|
||||
/* Save address split in Base Address H & L */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_BAD_H,
|
||||
(c_addr >> 16) & 0xffff);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_BAD_L,
|
||||
c_addr & 0xffff);
|
||||
|
||||
/* SAD = BAD */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_SAD_H,
|
||||
(c_addr >> 16) & 0xffff);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_SAD_L,
|
||||
c_addr & 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
static void resizer_configure(struct iss_resizer_device *resizer)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(resizer);
|
||||
struct v4l2_mbus_framefmt *informat, *outformat;
|
||||
|
||||
informat = &resizer->formats[RESIZER_PAD_SINK];
|
||||
outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM];
|
||||
|
||||
/* Disable pass-through more. Despite its name, the BYPASS bit controls
|
||||
* pass-through mode, not bypass mode.
|
||||
*/
|
||||
iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_FMT0,
|
||||
RSZ_SRC_FMT0_BYPASS);
|
||||
|
||||
/* Select RSZ input */
|
||||
iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_FMT0,
|
||||
RSZ_SRC_FMT0_SEL,
|
||||
resizer->input == RESIZER_INPUT_IPIPEIF ?
|
||||
RSZ_SRC_FMT0_SEL : 0);
|
||||
|
||||
/* RSZ ignores WEN signal from IPIPE/IPIPEIF */
|
||||
iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_MODE,
|
||||
RSZ_SRC_MODE_WRT);
|
||||
|
||||
/* Set Resizer in free-running mode */
|
||||
iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_MODE,
|
||||
RSZ_SRC_MODE_OST);
|
||||
|
||||
/* Init Resizer A */
|
||||
iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_MODE,
|
||||
RZA_MODE_ONE_SHOT);
|
||||
|
||||
/* Set size related things now */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_VPS, 0);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_HPS, 0);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_VSZ,
|
||||
informat->height - 2);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_HSZ,
|
||||
informat->width - 1);
|
||||
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_I_VPS, 0);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_I_HPS, 0);
|
||||
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_O_VSZ,
|
||||
outformat->height - 2);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_O_HSZ,
|
||||
outformat->width - 1);
|
||||
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_V_DIF, 0x100);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_H_DIF, 0x100);
|
||||
|
||||
/* Buffer output settings */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_PTR_S, 0);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_PTR_E,
|
||||
outformat->height - 1);
|
||||
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_OFT,
|
||||
resizer->video_out.bpl_value);
|
||||
|
||||
/* UYVY -> NV12 conversion */
|
||||
if ((informat->code == MEDIA_BUS_FMT_UYVY8_1X16) &&
|
||||
(outformat->code == MEDIA_BUS_FMT_YUYV8_1_5X8)) {
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_420,
|
||||
RSZ_420_CEN | RSZ_420_YEN);
|
||||
|
||||
/* UV Buffer output settings */
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_PTR_S,
|
||||
0);
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_PTR_E,
|
||||
outformat->height - 1);
|
||||
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_OFT,
|
||||
resizer->video_out.bpl_value);
|
||||
} else {
|
||||
iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_420, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Interrupt handling
|
||||
*/
|
||||
|
||||
static void resizer_isr_buffer(struct iss_resizer_device *resizer)
|
||||
{
|
||||
struct iss_buffer *buffer;
|
||||
|
||||
/* The whole resizer needs to be stopped. Disabling RZA only produces
|
||||
* input FIFO overflows, most probably when the next frame is received.
|
||||
*/
|
||||
resizer_enable(resizer, 0);
|
||||
|
||||
buffer = omap4iss_video_buffer_next(&resizer->video_out);
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
resizer_set_outaddr(resizer, buffer->iss_addr);
|
||||
|
||||
resizer_enable(resizer, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* omap4iss_resizer_isr - Configure resizer during interframe time.
|
||||
* @resizer: Pointer to ISP RESIZER device.
|
||||
* @events: RESIZER events
|
||||
*/
|
||||
void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events)
|
||||
{
|
||||
struct iss_device *iss = to_iss_device(resizer);
|
||||
struct iss_pipeline *pipe =
|
||||
to_iss_pipeline(&resizer->subdev.entity);
|
||||
|
||||
if (events & (ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR |
|
||||
ISP5_IRQ_RSZ_FIFO_OVF)) {
|
||||
dev_dbg(iss->dev, "RSZ Err: FIFO_IN_BLK:%d, FIFO_OVF:%d\n",
|
||||
events & ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR ? 1 : 0,
|
||||
events & ISP5_IRQ_RSZ_FIFO_OVF ? 1 : 0);
|
||||
omap4iss_pipeline_cancel_stream(pipe);
|
||||
}
|
||||
|
||||
if (omap4iss_module_sync_is_stopping(&resizer->wait,
|
||||
&resizer->stopping))
|
||||
return;
|
||||
|
||||
if (events & ISP5_IRQ_RSZ_INT_DMA)
|
||||
resizer_isr_buffer(resizer);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ISS video operations
|
||||
*/
|
||||
|
||||
static int resizer_video_queue(struct iss_video *video,
|
||||
struct iss_buffer *buffer)
|
||||
{
|
||||
struct iss_resizer_device *resizer = container_of(video,
|
||||
struct iss_resizer_device, video_out);
|
||||
|
||||
if (!(resizer->output & RESIZER_OUTPUT_MEMORY))
|
||||
return -ENODEV;
|
||||
|
||||
resizer_set_outaddr(resizer, buffer->iss_addr);
|
||||
|
||||
/*
|
||||
* If streaming was enabled before there was a buffer queued
|
||||
* or underrun happened in the ISR, the hardware was not enabled
|
||||
* and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set.
|
||||
* Enable it now.
|
||||
*/
|
||||
if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
|
||||
resizer_enable(resizer, 1);
|
||||
iss_video_dmaqueue_flags_clr(video);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iss_video_operations resizer_video_ops = {
|
||||
.queue = resizer_video_queue,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* V4L2 subdev operations
|
||||
*/
|
||||
|
||||
/*
|
||||
* resizer_set_stream - Enable/Disable streaming on the RESIZER module
|
||||
* @sd: ISP RESIZER V4L2 subdevice
|
||||
* @enable: Enable/disable stream
|
||||
*/
|
||||
static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
|
||||
struct iss_device *iss = to_iss_device(resizer);
|
||||
struct iss_video *video_out = &resizer->video_out;
|
||||
int ret = 0;
|
||||
|
||||
if (resizer->state == ISS_PIPELINE_STREAM_STOPPED) {
|
||||
if (enable == ISS_PIPELINE_STREAM_STOPPED)
|
||||
return 0;
|
||||
|
||||
omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ);
|
||||
|
||||
iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_MMR,
|
||||
RSZ_GCK_MMR_MMR);
|
||||
iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_SDR,
|
||||
RSZ_GCK_SDR_CORE);
|
||||
|
||||
/* FIXME: Enable RSZB also */
|
||||
iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SYSCONFIG,
|
||||
RSZ_SYSCONFIG_RSZA_CLK_EN);
|
||||
}
|
||||
|
||||
switch (enable) {
|
||||
case ISS_PIPELINE_STREAM_CONTINUOUS:
|
||||
|
||||
resizer_configure(resizer);
|
||||
resizer_print_status(resizer);
|
||||
|
||||
/*
|
||||
* When outputting to memory with no buffer available, let the
|
||||
* buffer queue handler start the hardware. A DMA queue flag
|
||||
* ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
|
||||
* a buffer available.
|
||||
*/
|
||||
if (resizer->output & RESIZER_OUTPUT_MEMORY &&
|
||||
!(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED))
|
||||
break;
|
||||
|
||||
atomic_set(&resizer->stopping, 0);
|
||||
resizer_enable(resizer, 1);
|
||||
iss_video_dmaqueue_flags_clr(video_out);
|
||||
break;
|
||||
|
||||
case ISS_PIPELINE_STREAM_STOPPED:
|
||||
if (resizer->state == ISS_PIPELINE_STREAM_STOPPED)
|
||||
return 0;
|
||||
if (omap4iss_module_sync_idle(&sd->entity, &resizer->wait,
|
||||
&resizer->stopping))
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
resizer_enable(resizer, 0);
|
||||
iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SYSCONFIG,
|
||||
RSZ_SYSCONFIG_RSZA_CLK_EN);
|
||||
iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_SDR,
|
||||
RSZ_GCK_SDR_CORE);
|
||||
iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_MMR,
|
||||
RSZ_GCK_MMR_MMR);
|
||||
omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ);
|
||||
iss_video_dmaqueue_flags_clr(video_out);
|
||||
break;
|
||||
}
|
||||
|
||||
resizer->state = enable;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct v4l2_mbus_framefmt *
|
||||
__resizer_get_format(struct iss_resizer_device *resizer,
|
||||
struct v4l2_subdev_state *sd_state, unsigned int pad,
|
||||
enum v4l2_subdev_format_whence which)
|
||||
{
|
||||
if (which == V4L2_SUBDEV_FORMAT_TRY)
|
||||
return v4l2_subdev_state_get_format(sd_state, pad);
|
||||
return &resizer->formats[pad];
|
||||
}
|
||||
|
||||
/*
|
||||
* resizer_try_format - Try video format on a pad
|
||||
* @resizer: ISS RESIZER device
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @pad: Pad number
|
||||
* @fmt: Format
|
||||
*/
|
||||
static void
|
||||
resizer_try_format(struct iss_resizer_device *resizer,
|
||||
struct v4l2_subdev_state *sd_state, unsigned int pad,
|
||||
struct v4l2_mbus_framefmt *fmt,
|
||||
enum v4l2_subdev_format_whence which)
|
||||
{
|
||||
u32 pixelcode;
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
unsigned int width = fmt->width;
|
||||
unsigned int height = fmt->height;
|
||||
unsigned int i;
|
||||
|
||||
switch (pad) {
|
||||
case RESIZER_PAD_SINK:
|
||||
for (i = 0; i < ARRAY_SIZE(resizer_fmts); i++) {
|
||||
if (fmt->code == resizer_fmts[i])
|
||||
break;
|
||||
}
|
||||
|
||||
/* If not found, use UYVY as default */
|
||||
if (i >= ARRAY_SIZE(resizer_fmts))
|
||||
fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||
|
||||
/* Clamp the input size. */
|
||||
fmt->width = clamp_t(u32, width, 1, 8192);
|
||||
fmt->height = clamp_t(u32, height, 1, 8192);
|
||||
break;
|
||||
|
||||
case RESIZER_PAD_SOURCE_MEM:
|
||||
pixelcode = fmt->code;
|
||||
format = __resizer_get_format(resizer, sd_state,
|
||||
RESIZER_PAD_SINK,
|
||||
which);
|
||||
memcpy(fmt, format, sizeof(*fmt));
|
||||
|
||||
if ((pixelcode == MEDIA_BUS_FMT_YUYV8_1_5X8) &&
|
||||
(fmt->code == MEDIA_BUS_FMT_UYVY8_1X16))
|
||||
fmt->code = pixelcode;
|
||||
|
||||
/* The data formatter truncates the number of horizontal output
|
||||
* pixels to a multiple of 16. To avoid clipping data, allow
|
||||
* callers to request an output size bigger than the input size
|
||||
* up to the nearest multiple of 16.
|
||||
*/
|
||||
fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15);
|
||||
fmt->width &= ~15;
|
||||
fmt->height = clamp_t(u32, height, 32, fmt->height);
|
||||
break;
|
||||
}
|
||||
|
||||
fmt->colorspace = V4L2_COLORSPACE_JPEG;
|
||||
fmt->field = V4L2_FIELD_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* resizer_enum_mbus_code - Handle pixel format enumeration
|
||||
* @sd : pointer to v4l2 subdev structure
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @code : pointer to v4l2_subdev_mbus_code_enum structure
|
||||
* return -EINVAL or zero on success
|
||||
*/
|
||||
static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_mbus_code_enum *code)
|
||||
{
|
||||
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
|
||||
switch (code->pad) {
|
||||
case RESIZER_PAD_SINK:
|
||||
if (code->index >= ARRAY_SIZE(resizer_fmts))
|
||||
return -EINVAL;
|
||||
|
||||
code->code = resizer_fmts[code->index];
|
||||
break;
|
||||
|
||||
case RESIZER_PAD_SOURCE_MEM:
|
||||
format = __resizer_get_format(resizer, sd_state,
|
||||
RESIZER_PAD_SINK,
|
||||
code->which);
|
||||
|
||||
if (code->index == 0) {
|
||||
code->code = format->code;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (format->code) {
|
||||
case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||
if (code->index == 1)
|
||||
code->code = MEDIA_BUS_FMT_YUYV8_1_5X8;
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
if (code->index != 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int resizer_enum_frame_size(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_frame_size_enum *fse)
|
||||
{
|
||||
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt format;
|
||||
|
||||
if (fse->index != 0)
|
||||
return -EINVAL;
|
||||
|
||||
format.code = fse->code;
|
||||
format.width = 1;
|
||||
format.height = 1;
|
||||
resizer_try_format(resizer, sd_state, fse->pad, &format, fse->which);
|
||||
fse->min_width = format.width;
|
||||
fse->min_height = format.height;
|
||||
|
||||
if (format.code != fse->code)
|
||||
return -EINVAL;
|
||||
|
||||
format.code = fse->code;
|
||||
format.width = -1;
|
||||
format.height = -1;
|
||||
resizer_try_format(resizer, sd_state, fse->pad, &format, fse->which);
|
||||
fse->max_width = format.width;
|
||||
fse->max_height = format.height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* resizer_get_format - Retrieve the video format on a pad
|
||||
* @sd : ISP RESIZER V4L2 subdevice
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @fmt: Format
|
||||
*
|
||||
* Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
|
||||
* to the format type.
|
||||
*/
|
||||
static int resizer_get_format(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_format *fmt)
|
||||
{
|
||||
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
|
||||
format = __resizer_get_format(resizer, sd_state, fmt->pad, fmt->which);
|
||||
if (!format)
|
||||
return -EINVAL;
|
||||
|
||||
fmt->format = *format;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* resizer_set_format - Set the video format on a pad
|
||||
* @sd : ISP RESIZER V4L2 subdevice
|
||||
* @sd_state: V4L2 subdev state
|
||||
* @fmt: Format
|
||||
*
|
||||
* Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
|
||||
* to the format type.
|
||||
*/
|
||||
static int resizer_set_format(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_format *fmt)
|
||||
{
|
||||
struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
|
||||
format = __resizer_get_format(resizer, sd_state, fmt->pad, fmt->which);
|
||||
if (!format)
|
||||
return -EINVAL;
|
||||
|
||||
resizer_try_format(resizer, sd_state, fmt->pad, &fmt->format,
|
||||
fmt->which);
|
||||
*format = fmt->format;
|
||||
|
||||
/* Propagate the format from sink to source */
|
||||
if (fmt->pad == RESIZER_PAD_SINK) {
|
||||
format = __resizer_get_format(resizer, sd_state,
|
||||
RESIZER_PAD_SOURCE_MEM,
|
||||
fmt->which);
|
||||
*format = fmt->format;
|
||||
resizer_try_format(resizer, sd_state, RESIZER_PAD_SOURCE_MEM,
|
||||
format,
|
||||
fmt->which);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int resizer_link_validate(struct v4l2_subdev *sd,
|
||||
struct media_link *link,
|
||||
struct v4l2_subdev_format *source_fmt,
|
||||
struct v4l2_subdev_format *sink_fmt)
|
||||
{
|
||||
/* Check if the two ends match */
|
||||
if (source_fmt->format.width != sink_fmt->format.width ||
|
||||
source_fmt->format.height != sink_fmt->format.height)
|
||||
return -EPIPE;
|
||||
|
||||
if (source_fmt->format.code != sink_fmt->format.code)
|
||||
return -EPIPE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* resizer_init_formats - Initialize formats on all pads
|
||||
* @sd: ISP RESIZER V4L2 subdevice
|
||||
* @fh: V4L2 subdev file handle
|
||||
*
|
||||
* Initialize all pad formats with default values. If fh is not NULL, try
|
||||
* formats are initialized on the file handle. Otherwise active formats are
|
||||
* initialized on the device.
|
||||
*/
|
||||
static int resizer_init_formats(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
struct v4l2_subdev_format format;
|
||||
|
||||
memset(&format, 0, sizeof(format));
|
||||
format.pad = RESIZER_PAD_SINK;
|
||||
format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
format.format.code = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||
format.format.width = 4096;
|
||||
format.format.height = 4096;
|
||||
resizer_set_format(sd, fh ? fh->state : NULL, &format);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* V4L2 subdev video operations */
|
||||
static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = {
|
||||
.s_stream = resizer_set_stream,
|
||||
};
|
||||
|
||||
/* V4L2 subdev pad operations */
|
||||
static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = {
|
||||
.enum_mbus_code = resizer_enum_mbus_code,
|
||||
.enum_frame_size = resizer_enum_frame_size,
|
||||
.get_fmt = resizer_get_format,
|
||||
.set_fmt = resizer_set_format,
|
||||
.link_validate = resizer_link_validate,
|
||||
};
|
||||
|
||||
/* V4L2 subdev operations */
|
||||
static const struct v4l2_subdev_ops resizer_v4l2_ops = {
|
||||
.video = &resizer_v4l2_video_ops,
|
||||
.pad = &resizer_v4l2_pad_ops,
|
||||
};
|
||||
|
||||
/* V4L2 subdev internal operations */
|
||||
static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = {
|
||||
.open = resizer_init_formats,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Media entity operations
|
||||
*/
|
||||
|
||||
/*
|
||||
* resizer_link_setup - Setup RESIZER connections
|
||||
* @entity: RESIZER media entity
|
||||
* @local: Pad at the local end of the link
|
||||
* @remote: Pad at the remote end of the link
|
||||
* @flags: Link flags
|
||||
*
|
||||
* return -EINVAL or zero on success
|
||||
*/
|
||||
static int resizer_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 iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
|
||||
struct iss_device *iss = to_iss_device(resizer);
|
||||
unsigned int index = local->index;
|
||||
|
||||
/* FIXME: this is actually a hack! */
|
||||
if (is_media_entity_v4l2_subdev(remote->entity))
|
||||
index |= 2 << 16;
|
||||
|
||||
switch (index) {
|
||||
case RESIZER_PAD_SINK | 2 << 16:
|
||||
/* Read from IPIPE or IPIPEIF. */
|
||||
if (!(flags & MEDIA_LNK_FL_ENABLED)) {
|
||||
resizer->input = RESIZER_INPUT_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (resizer->input != RESIZER_INPUT_NONE)
|
||||
return -EBUSY;
|
||||
|
||||
if (remote->entity == &iss->ipipeif.subdev.entity)
|
||||
resizer->input = RESIZER_INPUT_IPIPEIF;
|
||||
else if (remote->entity == &iss->ipipe.subdev.entity)
|
||||
resizer->input = RESIZER_INPUT_IPIPE;
|
||||
|
||||
break;
|
||||
|
||||
case RESIZER_PAD_SOURCE_MEM:
|
||||
/* Write to memory */
|
||||
if (flags & MEDIA_LNK_FL_ENABLED) {
|
||||
if (resizer->output & ~RESIZER_OUTPUT_MEMORY)
|
||||
return -EBUSY;
|
||||
resizer->output |= RESIZER_OUTPUT_MEMORY;
|
||||
} else {
|
||||
resizer->output &= ~RESIZER_OUTPUT_MEMORY;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* media operations */
|
||||
static const struct media_entity_operations resizer_media_ops = {
|
||||
.link_setup = resizer_link_setup,
|
||||
.link_validate = v4l2_subdev_link_validate,
|
||||
};
|
||||
|
||||
/*
|
||||
* resizer_init_entities - Initialize V4L2 subdev and media entity
|
||||
* @resizer: ISS ISP RESIZER module
|
||||
*
|
||||
* Return 0 on success and a negative error code on failure.
|
||||
*/
|
||||
static int resizer_init_entities(struct iss_resizer_device *resizer)
|
||||
{
|
||||
struct v4l2_subdev *sd = &resizer->subdev;
|
||||
struct media_pad *pads = resizer->pads;
|
||||
struct media_entity *me = &sd->entity;
|
||||
int ret;
|
||||
|
||||
resizer->input = RESIZER_INPUT_NONE;
|
||||
|
||||
v4l2_subdev_init(sd, &resizer_v4l2_ops);
|
||||
sd->internal_ops = &resizer_v4l2_internal_ops;
|
||||
strscpy(sd->name, "OMAP4 ISS ISP resizer", sizeof(sd->name));
|
||||
sd->grp_id = BIT(16); /* group ID for iss subdevs */
|
||||
v4l2_set_subdevdata(sd, resizer);
|
||||
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
|
||||
pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
|
||||
pads[RESIZER_PAD_SOURCE_MEM].flags = MEDIA_PAD_FL_SOURCE;
|
||||
|
||||
me->ops = &resizer_media_ops;
|
||||
ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
resizer_init_formats(sd, NULL);
|
||||
|
||||
resizer->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
resizer->video_out.ops = &resizer_video_ops;
|
||||
resizer->video_out.iss = to_iss_device(resizer);
|
||||
resizer->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
|
||||
resizer->video_out.bpl_alignment = 32;
|
||||
resizer->video_out.bpl_zero_padding = 1;
|
||||
resizer->video_out.bpl_max = 0x1ffe0;
|
||||
|
||||
return omap4iss_video_init(&resizer->video_out, "ISP resizer a");
|
||||
}
|
||||
|
||||
void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer)
|
||||
{
|
||||
v4l2_device_unregister_subdev(&resizer->subdev);
|
||||
omap4iss_video_unregister(&resizer->video_out);
|
||||
}
|
||||
|
||||
int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer,
|
||||
struct v4l2_device *vdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Register the subdev and video node. */
|
||||
ret = v4l2_device_register_subdev(vdev, &resizer->subdev);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = omap4iss_video_register(&resizer->video_out, vdev);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
omap4iss_resizer_unregister_entities(resizer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ISP RESIZER initialisation and cleanup
|
||||
*/
|
||||
|
||||
/*
|
||||
* omap4iss_resizer_init - RESIZER module initialization.
|
||||
* @iss: Device pointer specific to the OMAP4 ISS.
|
||||
*
|
||||
* TODO: Get the initialisation values from platform data.
|
||||
*
|
||||
* Return 0 on success or a negative error code otherwise.
|
||||
*/
|
||||
int omap4iss_resizer_init(struct iss_device *iss)
|
||||
{
|
||||
struct iss_resizer_device *resizer = &iss->resizer;
|
||||
|
||||
resizer->state = ISS_PIPELINE_STREAM_STOPPED;
|
||||
init_waitqueue_head(&resizer->wait);
|
||||
|
||||
return resizer_init_entities(resizer);
|
||||
}
|
||||
|
||||
/*
|
||||
* omap4iss_resizer_create_links() - RESIZER pads links creation
|
||||
* @iss: Pointer to ISS device
|
||||
*
|
||||
* return negative error code or zero on success
|
||||
*/
|
||||
int omap4iss_resizer_create_links(struct iss_device *iss)
|
||||
{
|
||||
struct iss_resizer_device *resizer = &iss->resizer;
|
||||
|
||||
/* Connect the RESIZER subdev to the video node. */
|
||||
return media_create_pad_link(&resizer->subdev.entity,
|
||||
RESIZER_PAD_SOURCE_MEM,
|
||||
&resizer->video_out.video.entity, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* omap4iss_resizer_cleanup - RESIZER module cleanup.
|
||||
* @iss: Device pointer specific to the OMAP4 ISS.
|
||||
*/
|
||||
void omap4iss_resizer_cleanup(struct iss_device *iss)
|
||||
{
|
||||
struct iss_resizer_device *resizer = &iss->resizer;
|
||||
|
||||
media_entity_cleanup(&resizer->subdev.entity);
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - ISP RESIZER module
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef OMAP4_ISS_RESIZER_H
|
||||
#define OMAP4_ISS_RESIZER_H
|
||||
|
||||
#include "iss_video.h"
|
||||
|
||||
enum resizer_input_entity {
|
||||
RESIZER_INPUT_NONE,
|
||||
RESIZER_INPUT_IPIPE,
|
||||
RESIZER_INPUT_IPIPEIF
|
||||
};
|
||||
|
||||
#define RESIZER_OUTPUT_MEMORY BIT(0)
|
||||
|
||||
/* Sink and source RESIZER pads */
|
||||
#define RESIZER_PAD_SINK 0
|
||||
#define RESIZER_PAD_SOURCE_MEM 1
|
||||
#define RESIZER_PADS_NUM 2
|
||||
|
||||
/*
|
||||
* struct iss_resizer_device - Structure for the RESIZER module to store its own
|
||||
* information
|
||||
* @subdev: V4L2 subdevice
|
||||
* @pads: Sink and source media entity pads
|
||||
* @formats: Active video formats
|
||||
* @input: Active input
|
||||
* @output: Active outputs
|
||||
* @video_out: Output video node
|
||||
* @error: A hardware error occurred during capture
|
||||
* @state: Streaming state
|
||||
* @wait: Wait queue used to stop the module
|
||||
* @stopping: Stopping state
|
||||
*/
|
||||
struct iss_resizer_device {
|
||||
struct v4l2_subdev subdev;
|
||||
struct media_pad pads[RESIZER_PADS_NUM];
|
||||
struct v4l2_mbus_framefmt formats[RESIZER_PADS_NUM];
|
||||
|
||||
enum resizer_input_entity input;
|
||||
unsigned int output;
|
||||
struct iss_video video_out;
|
||||
unsigned int error;
|
||||
|
||||
enum iss_pipeline_stream_state state;
|
||||
wait_queue_head_t wait;
|
||||
atomic_t stopping;
|
||||
};
|
||||
|
||||
struct iss_device;
|
||||
|
||||
int omap4iss_resizer_init(struct iss_device *iss);
|
||||
int omap4iss_resizer_create_links(struct iss_device *iss);
|
||||
void omap4iss_resizer_cleanup(struct iss_device *iss);
|
||||
int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer,
|
||||
struct v4l2_device *vdev);
|
||||
void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer);
|
||||
|
||||
int omap4iss_resizer_busy(struct iss_resizer_device *resizer);
|
||||
void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events);
|
||||
void omap4iss_resizer_restore_context(struct iss_device *iss);
|
||||
void omap4iss_resizer_max_rate(struct iss_resizer_device *resizer,
|
||||
unsigned int *max_rate);
|
||||
|
||||
#endif /* OMAP4_ISS_RESIZER_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,203 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* TI OMAP4 ISS V4L2 Driver - Generic video node
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef OMAP4_ISS_VIDEO_H
|
||||
#define OMAP4_ISS_VIDEO_H
|
||||
|
||||
#include <linux/v4l2-mediabus.h>
|
||||
#include <media/media-entity.h>
|
||||
#include <media/v4l2-dev.h>
|
||||
#include <media/v4l2-fh.h>
|
||||
#include <media/videobuf2-v4l2.h>
|
||||
#include <media/videobuf2-dma-contig.h>
|
||||
|
||||
#define ISS_VIDEO_DRIVER_NAME "issvideo"
|
||||
|
||||
struct iss_device;
|
||||
struct iss_video;
|
||||
struct v4l2_mbus_framefmt;
|
||||
struct v4l2_pix_format;
|
||||
|
||||
/*
|
||||
* struct iss_format_info - ISS media bus format information
|
||||
* @code: V4L2 media bus format code
|
||||
* @truncated: V4L2 media bus format code for the same format truncated to 10
|
||||
* bits. Identical to @code if the format is 10 bits wide or less.
|
||||
* @uncompressed: V4L2 media bus format code for the corresponding uncompressed
|
||||
* format. Identical to @code if the format is not DPCM compressed.
|
||||
* @flavor: V4L2 media bus format code for the same pixel layout but
|
||||
* shifted to be 8 bits per pixel. =0 if format is not shiftable.
|
||||
* @pixelformat: V4L2 pixel format FCC identifier
|
||||
* @bpp: Bits per pixel
|
||||
*/
|
||||
struct iss_format_info {
|
||||
u32 code;
|
||||
u32 truncated;
|
||||
u32 uncompressed;
|
||||
u32 flavor;
|
||||
u32 pixelformat;
|
||||
unsigned int bpp;
|
||||
};
|
||||
|
||||
enum iss_pipeline_stream_state {
|
||||
ISS_PIPELINE_STREAM_STOPPED = 0,
|
||||
ISS_PIPELINE_STREAM_CONTINUOUS = 1,
|
||||
ISS_PIPELINE_STREAM_SINGLESHOT = 2,
|
||||
};
|
||||
|
||||
enum iss_pipeline_state {
|
||||
/* The stream has been started on the input video node. */
|
||||
ISS_PIPELINE_STREAM_INPUT = BIT(0),
|
||||
/* The stream has been started on the output video node. */
|
||||
ISS_PIPELINE_STREAM_OUTPUT = BIT(1),
|
||||
/* At least one buffer is queued on the input video node. */
|
||||
ISS_PIPELINE_QUEUE_INPUT = BIT(2),
|
||||
/* At least one buffer is queued on the output video node. */
|
||||
ISS_PIPELINE_QUEUE_OUTPUT = BIT(3),
|
||||
/* The input entity is idle, ready to be started. */
|
||||
ISS_PIPELINE_IDLE_INPUT = BIT(4),
|
||||
/* The output entity is idle, ready to be started. */
|
||||
ISS_PIPELINE_IDLE_OUTPUT = BIT(5),
|
||||
/* The pipeline is currently streaming. */
|
||||
ISS_PIPELINE_STREAM = BIT(6),
|
||||
};
|
||||
|
||||
/*
|
||||
* struct iss_pipeline - An OMAP4 ISS hardware pipeline
|
||||
* @ent_enum: Entities in the pipeline
|
||||
* @error: A hardware error occurred during capture
|
||||
*/
|
||||
struct iss_pipeline {
|
||||
struct media_pipeline pipe;
|
||||
spinlock_t lock; /* Pipeline state and queue flags */
|
||||
unsigned int state;
|
||||
enum iss_pipeline_stream_state stream_state;
|
||||
struct iss_video *input;
|
||||
struct iss_video *output;
|
||||
struct media_entity_enum ent_enum;
|
||||
atomic_t frame_number;
|
||||
bool do_propagation; /* of frame number */
|
||||
bool error;
|
||||
struct v4l2_fract max_timeperframe;
|
||||
struct v4l2_subdev *external;
|
||||
unsigned int external_rate;
|
||||
int external_bpp;
|
||||
};
|
||||
|
||||
static inline struct iss_pipeline *to_iss_pipeline(struct media_entity *entity)
|
||||
{
|
||||
struct media_pipeline *pipe = media_entity_pipeline(entity);
|
||||
|
||||
if (!pipe)
|
||||
return NULL;
|
||||
|
||||
return container_of(pipe, struct iss_pipeline, pipe);
|
||||
}
|
||||
|
||||
static inline int iss_pipeline_ready(struct iss_pipeline *pipe)
|
||||
{
|
||||
return pipe->state == (ISS_PIPELINE_STREAM_INPUT |
|
||||
ISS_PIPELINE_STREAM_OUTPUT |
|
||||
ISS_PIPELINE_QUEUE_INPUT |
|
||||
ISS_PIPELINE_QUEUE_OUTPUT |
|
||||
ISS_PIPELINE_IDLE_INPUT |
|
||||
ISS_PIPELINE_IDLE_OUTPUT);
|
||||
}
|
||||
|
||||
/*
|
||||
* struct iss_buffer - ISS buffer
|
||||
* @buffer: ISS video buffer
|
||||
* @iss_addr: Physical address of the buffer.
|
||||
*/
|
||||
struct iss_buffer {
|
||||
/* common v4l buffer stuff -- must be first */
|
||||
struct vb2_v4l2_buffer vb;
|
||||
struct list_head list;
|
||||
dma_addr_t iss_addr;
|
||||
};
|
||||
|
||||
#define to_iss_buffer(buf) container_of(buf, struct iss_buffer, vb)
|
||||
|
||||
enum iss_video_dmaqueue_flags {
|
||||
/* Set if DMA queue becomes empty when ISS_PIPELINE_STREAM_CONTINUOUS */
|
||||
ISS_VIDEO_DMAQUEUE_UNDERRUN = BIT(0),
|
||||
/* Set when queuing buffer to an empty DMA queue */
|
||||
ISS_VIDEO_DMAQUEUE_QUEUED = BIT(1),
|
||||
};
|
||||
|
||||
#define iss_video_dmaqueue_flags_clr(video) \
|
||||
({ (video)->dmaqueue_flags = 0; })
|
||||
|
||||
/*
|
||||
* struct iss_video_operations - ISS video operations
|
||||
* @queue: Resume streaming when a buffer is queued. Called on VIDIOC_QBUF
|
||||
* if there was no buffer previously queued.
|
||||
*/
|
||||
struct iss_video_operations {
|
||||
int (*queue)(struct iss_video *video, struct iss_buffer *buffer);
|
||||
};
|
||||
|
||||
struct iss_video {
|
||||
struct video_device video;
|
||||
enum v4l2_buf_type type;
|
||||
struct media_pad pad;
|
||||
|
||||
struct mutex mutex; /* format and crop settings */
|
||||
atomic_t active;
|
||||
|
||||
struct iss_device *iss;
|
||||
|
||||
unsigned int capture_mem;
|
||||
unsigned int bpl_alignment; /* alignment value */
|
||||
unsigned int bpl_zero_padding; /* whether the alignment is optional */
|
||||
unsigned int bpl_max; /* maximum bytes per line value */
|
||||
unsigned int bpl_value; /* bytes per line value */
|
||||
unsigned int bpl_padding; /* padding at end of line */
|
||||
|
||||
/* Pipeline state */
|
||||
struct iss_pipeline pipe;
|
||||
struct mutex stream_lock; /* pipeline and stream states */
|
||||
bool error;
|
||||
|
||||
/* Video buffers queue */
|
||||
struct vb2_queue *queue;
|
||||
spinlock_t qlock; /* protects dmaqueue and error */
|
||||
struct list_head dmaqueue;
|
||||
enum iss_video_dmaqueue_flags dmaqueue_flags;
|
||||
|
||||
const struct iss_video_operations *ops;
|
||||
};
|
||||
|
||||
#define to_iss_video(vdev) container_of(vdev, struct iss_video, video)
|
||||
|
||||
struct iss_video_fh {
|
||||
struct v4l2_fh vfh;
|
||||
struct iss_video *video;
|
||||
struct vb2_queue queue;
|
||||
struct v4l2_format format;
|
||||
struct v4l2_fract timeperframe;
|
||||
};
|
||||
|
||||
#define to_iss_video_fh(fh) container_of(fh, struct iss_video_fh, vfh)
|
||||
#define iss_video_queue_to_iss_video_fh(q) \
|
||||
container_of(q, struct iss_video_fh, queue)
|
||||
|
||||
int omap4iss_video_init(struct iss_video *video, const char *name);
|
||||
void omap4iss_video_cleanup(struct iss_video *video);
|
||||
int omap4iss_video_register(struct iss_video *video,
|
||||
struct v4l2_device *vdev);
|
||||
void omap4iss_video_unregister(struct iss_video *video);
|
||||
struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video);
|
||||
void omap4iss_video_cancel_stream(struct iss_video *video);
|
||||
struct media_pad *omap4iss_video_remote_pad(struct iss_video *video);
|
||||
|
||||
const struct iss_format_info *
|
||||
omap4iss_video_format_info(u32 code);
|
||||
|
||||
#endif /* OMAP4_ISS_VIDEO_H */
|
@ -1,66 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef ARCH_ARM_PLAT_OMAP4_ISS_H
|
||||
#define ARCH_ARM_PLAT_OMAP4_ISS_H
|
||||
|
||||
#include <linux/i2c.h>
|
||||
|
||||
struct iss_device;
|
||||
|
||||
enum iss_interface_type {
|
||||
ISS_INTERFACE_CSI2A_PHY1,
|
||||
ISS_INTERFACE_CSI2B_PHY2,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iss_csiphy_lane: CSI2 lane position and polarity
|
||||
* @pos: position of the lane
|
||||
* @pol: polarity of the lane
|
||||
*/
|
||||
struct iss_csiphy_lane {
|
||||
u8 pos;
|
||||
u8 pol;
|
||||
};
|
||||
|
||||
#define ISS_CSIPHY1_NUM_DATA_LANES 4
|
||||
#define ISS_CSIPHY2_NUM_DATA_LANES 1
|
||||
|
||||
/**
|
||||
* struct iss_csiphy_lanes_cfg - CSI2 lane configuration
|
||||
* @data: Configuration of one or two data lanes
|
||||
* @clk: Clock lane configuration
|
||||
*/
|
||||
struct iss_csiphy_lanes_cfg {
|
||||
struct iss_csiphy_lane data[ISS_CSIPHY1_NUM_DATA_LANES];
|
||||
struct iss_csiphy_lane clk;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iss_csi2_platform_data - CSI2 interface platform data
|
||||
* @crc: Enable the cyclic redundancy check
|
||||
* @vpclk_div: Video port output clock control
|
||||
*/
|
||||
struct iss_csi2_platform_data {
|
||||
unsigned crc:1;
|
||||
unsigned vpclk_div:2;
|
||||
struct iss_csiphy_lanes_cfg lanecfg;
|
||||
};
|
||||
|
||||
struct iss_subdev_i2c_board_info {
|
||||
struct i2c_board_info *board_info;
|
||||
int i2c_adapter_id;
|
||||
};
|
||||
|
||||
struct iss_v4l2_subdevs_group {
|
||||
struct iss_subdev_i2c_board_info *subdevs;
|
||||
enum iss_interface_type interface;
|
||||
union {
|
||||
struct iss_csi2_platform_data csi2;
|
||||
} bus; /* gcc < 4.6.0 chokes on anonymous union initializers */
|
||||
};
|
||||
|
||||
struct iss_platform_data {
|
||||
struct iss_v4l2_subdevs_group *subdevs;
|
||||
void (*set_constraints)(struct iss_device *iss, bool enable);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user