18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * TI Camera Access Layer (CAL) 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2015-2020 Texas Instruments Inc. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Authors: 88c2ecf20Sopenharmony_ci * Benoit Parrot <bparrot@ti.com> 98c2ecf20Sopenharmony_ci * Laurent Pinchart <laurent.pinchart@ideasonboard.com> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci#ifndef __TI_CAL_H__ 128c2ecf20Sopenharmony_ci#define __TI_CAL_H__ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/bitfield.h> 158c2ecf20Sopenharmony_ci#include <linux/io.h> 168c2ecf20Sopenharmony_ci#include <linux/list.h> 178c2ecf20Sopenharmony_ci#include <linux/mutex.h> 188c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 198c2ecf20Sopenharmony_ci#include <linux/videodev2.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <media/media-device.h> 228c2ecf20Sopenharmony_ci#include <media/v4l2-async.h> 238c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h> 248c2ecf20Sopenharmony_ci#include <media/v4l2-dev.h> 258c2ecf20Sopenharmony_ci#include <media/v4l2-device.h> 268c2ecf20Sopenharmony_ci#include <media/v4l2-fwnode.h> 278c2ecf20Sopenharmony_ci#include <media/videobuf2-v4l2.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define CAL_MODULE_NAME "cal" 308c2ecf20Sopenharmony_ci#define CAL_NUM_CONTEXT 2 318c2ecf20Sopenharmony_ci#define CAL_NUM_CSI2_PORTS 2 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define MAX_WIDTH_BYTES (8192 * 8) 348c2ecf20Sopenharmony_ci#define MAX_HEIGHT_LINES 16383 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistruct device; 378c2ecf20Sopenharmony_cistruct device_node; 388c2ecf20Sopenharmony_cistruct resource; 398c2ecf20Sopenharmony_cistruct regmap; 408c2ecf20Sopenharmony_cistruct regmap_fied; 418c2ecf20Sopenharmony_cistruct v4l2_subdev; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* CTRL_CORE_CAMERRX_CONTROL register field id */ 448c2ecf20Sopenharmony_cienum cal_camerarx_field { 458c2ecf20Sopenharmony_ci F_CTRLCLKEN, 468c2ecf20Sopenharmony_ci F_CAMMODE, 478c2ecf20Sopenharmony_ci F_LANEENABLE, 488c2ecf20Sopenharmony_ci F_CSI_MODE, 498c2ecf20Sopenharmony_ci F_MAX_FIELDS, 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistruct cal_fmt { 538c2ecf20Sopenharmony_ci u32 fourcc; 548c2ecf20Sopenharmony_ci u32 code; 558c2ecf20Sopenharmony_ci /* Bits per pixel */ 568c2ecf20Sopenharmony_ci u8 bpp; 578c2ecf20Sopenharmony_ci}; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* buffer for one video frame */ 608c2ecf20Sopenharmony_cistruct cal_buffer { 618c2ecf20Sopenharmony_ci /* common v4l buffer stuff -- must be first */ 628c2ecf20Sopenharmony_ci struct vb2_v4l2_buffer vb; 638c2ecf20Sopenharmony_ci struct list_head list; 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistruct cal_dmaqueue { 678c2ecf20Sopenharmony_ci struct list_head active; 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistruct cal_camerarx_data { 718c2ecf20Sopenharmony_ci struct { 728c2ecf20Sopenharmony_ci unsigned int lsb; 738c2ecf20Sopenharmony_ci unsigned int msb; 748c2ecf20Sopenharmony_ci } fields[F_MAX_FIELDS]; 758c2ecf20Sopenharmony_ci unsigned int num_lanes; 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistruct cal_data { 798c2ecf20Sopenharmony_ci const struct cal_camerarx_data *camerarx; 808c2ecf20Sopenharmony_ci unsigned int num_csi2_phy; 818c2ecf20Sopenharmony_ci unsigned int flags; 828c2ecf20Sopenharmony_ci}; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/* 858c2ecf20Sopenharmony_ci * The Camera Adaptation Layer (CAL) module is paired with one or more complex 868c2ecf20Sopenharmony_ci * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and 878c2ecf20Sopenharmony_ci * DMA contexts. 888c2ecf20Sopenharmony_ci * 898c2ecf20Sopenharmony_ci * The cal_dev structure represents the whole subsystem, including the CAL and 908c2ecf20Sopenharmony_ci * the CAMERARX instances. Instances of struct cal_dev are named cal through the 918c2ecf20Sopenharmony_ci * driver. 928c2ecf20Sopenharmony_ci * 938c2ecf20Sopenharmony_ci * The cal_camerarx structure represents one CAMERARX instance. Instances of 948c2ecf20Sopenharmony_ci * cal_camerarx are named phy through the driver. 958c2ecf20Sopenharmony_ci * 968c2ecf20Sopenharmony_ci * The cal_ctx structure represents the combination of one CSI-2 context, one 978c2ecf20Sopenharmony_ci * processing context and one DMA context. Instance of struct cal_ctx are named 988c2ecf20Sopenharmony_ci * ctx through the driver. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistruct cal_camerarx { 1028c2ecf20Sopenharmony_ci void __iomem *base; 1038c2ecf20Sopenharmony_ci struct resource *res; 1048c2ecf20Sopenharmony_ci struct device *dev; 1058c2ecf20Sopenharmony_ci struct regmap_field *fields[F_MAX_FIELDS]; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci struct cal_dev *cal; 1088c2ecf20Sopenharmony_ci unsigned int instance; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci struct v4l2_fwnode_endpoint endpoint; 1118c2ecf20Sopenharmony_ci struct device_node *sensor_node; 1128c2ecf20Sopenharmony_ci struct v4l2_subdev *sensor; 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistruct cal_dev { 1168c2ecf20Sopenharmony_ci struct clk *fclk; 1178c2ecf20Sopenharmony_ci int irq; 1188c2ecf20Sopenharmony_ci void __iomem *base; 1198c2ecf20Sopenharmony_ci struct resource *res; 1208c2ecf20Sopenharmony_ci struct device *dev; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci const struct cal_data *data; 1238c2ecf20Sopenharmony_ci u32 revision; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* Control Module handle */ 1268c2ecf20Sopenharmony_ci struct regmap *syscon_camerrx; 1278c2ecf20Sopenharmony_ci u32 syscon_camerrx_offset; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* Camera Core Module handle */ 1308c2ecf20Sopenharmony_ci struct cal_camerarx *phy[CAL_NUM_CSI2_PORTS]; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci struct cal_ctx *ctx[CAL_NUM_CONTEXT]; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci struct media_device mdev; 1358c2ecf20Sopenharmony_ci struct v4l2_device v4l2_dev; 1368c2ecf20Sopenharmony_ci struct v4l2_async_notifier notifier; 1378c2ecf20Sopenharmony_ci}; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/* 1408c2ecf20Sopenharmony_ci * There is one cal_ctx structure for each camera core context. 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_cistruct cal_ctx { 1438c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler ctrl_handler; 1448c2ecf20Sopenharmony_ci struct video_device vdev; 1458c2ecf20Sopenharmony_ci struct media_pad pad; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci struct cal_dev *cal; 1488c2ecf20Sopenharmony_ci struct cal_camerarx *phy; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* v4l2_ioctl mutex */ 1518c2ecf20Sopenharmony_ci struct mutex mutex; 1528c2ecf20Sopenharmony_ci /* v4l2 buffers lock */ 1538c2ecf20Sopenharmony_ci spinlock_t slock; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci struct cal_dmaqueue vidq; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* video capture */ 1588c2ecf20Sopenharmony_ci const struct cal_fmt *fmt; 1598c2ecf20Sopenharmony_ci /* Used to store current pixel format */ 1608c2ecf20Sopenharmony_ci struct v4l2_format v_fmt; 1618c2ecf20Sopenharmony_ci /* Used to store current mbus frame format */ 1628c2ecf20Sopenharmony_ci struct v4l2_mbus_framefmt m_fmt; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci /* Current subdev enumerated format */ 1658c2ecf20Sopenharmony_ci const struct cal_fmt **active_fmt; 1668c2ecf20Sopenharmony_ci unsigned int num_active_fmt; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci unsigned int sequence; 1698c2ecf20Sopenharmony_ci struct vb2_queue vb_vidq; 1708c2ecf20Sopenharmony_ci unsigned int index; 1718c2ecf20Sopenharmony_ci unsigned int cport; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* Pointer pointing to current v4l2_buffer */ 1748c2ecf20Sopenharmony_ci struct cal_buffer *cur_frm; 1758c2ecf20Sopenharmony_ci /* Pointer pointing to next v4l2_buffer */ 1768c2ecf20Sopenharmony_ci struct cal_buffer *next_frm; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci bool dma_act; 1798c2ecf20Sopenharmony_ci}; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ciextern unsigned int cal_debug; 1828c2ecf20Sopenharmony_ciextern int cal_video_nr; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci#define cal_dbg(level, cal, fmt, arg...) \ 1858c2ecf20Sopenharmony_ci do { \ 1868c2ecf20Sopenharmony_ci if (cal_debug >= (level)) \ 1878c2ecf20Sopenharmony_ci dev_printk(KERN_DEBUG, (cal)->dev, fmt, ##arg); \ 1888c2ecf20Sopenharmony_ci } while (0) 1898c2ecf20Sopenharmony_ci#define cal_info(cal, fmt, arg...) \ 1908c2ecf20Sopenharmony_ci dev_info((cal)->dev, fmt, ##arg) 1918c2ecf20Sopenharmony_ci#define cal_err(cal, fmt, arg...) \ 1928c2ecf20Sopenharmony_ci dev_err((cal)->dev, fmt, ##arg) 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci#define ctx_dbg(level, ctx, fmt, arg...) \ 1958c2ecf20Sopenharmony_ci cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg) 1968c2ecf20Sopenharmony_ci#define ctx_info(ctx, fmt, arg...) \ 1978c2ecf20Sopenharmony_ci cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg) 1988c2ecf20Sopenharmony_ci#define ctx_err(ctx, fmt, arg...) \ 1998c2ecf20Sopenharmony_ci cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg) 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci#define phy_dbg(level, phy, fmt, arg...) \ 2028c2ecf20Sopenharmony_ci cal_dbg(level, (phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg) 2038c2ecf20Sopenharmony_ci#define phy_info(phy, fmt, arg...) \ 2048c2ecf20Sopenharmony_ci cal_info((phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg) 2058c2ecf20Sopenharmony_ci#define phy_err(phy, fmt, arg...) \ 2068c2ecf20Sopenharmony_ci cal_err((phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg) 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic inline u32 cal_read(struct cal_dev *cal, u32 offset) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci return ioread32(cal->base + offset); 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic inline void cal_write(struct cal_dev *cal, u32 offset, u32 val) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci iowrite32(val, cal->base + offset); 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic __always_inline u32 cal_read_field(struct cal_dev *cal, u32 offset, u32 mask) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci return FIELD_GET(mask, cal_read(cal, offset)); 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic inline void cal_write_field(struct cal_dev *cal, u32 offset, u32 value, 2248c2ecf20Sopenharmony_ci u32 mask) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci u32 val = cal_read(cal, offset); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci val &= ~mask; 2298c2ecf20Sopenharmony_ci val |= (value << __ffs(mask)) & mask; 2308c2ecf20Sopenharmony_ci cal_write(cal, offset, val); 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic inline void cal_set_field(u32 *valp, u32 field, u32 mask) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci u32 val = *valp; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci val &= ~mask; 2388c2ecf20Sopenharmony_ci val |= (field << __ffs(mask)) & mask; 2398c2ecf20Sopenharmony_ci *valp = val; 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_civoid cal_quickdump_regs(struct cal_dev *cal); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_civoid cal_camerarx_disable(struct cal_camerarx *phy); 2458c2ecf20Sopenharmony_ciint cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt); 2468c2ecf20Sopenharmony_civoid cal_camerarx_stop(struct cal_camerarx *phy); 2478c2ecf20Sopenharmony_civoid cal_camerarx_enable_irqs(struct cal_camerarx *phy); 2488c2ecf20Sopenharmony_civoid cal_camerarx_disable_irqs(struct cal_camerarx *phy); 2498c2ecf20Sopenharmony_civoid cal_camerarx_ppi_enable(struct cal_camerarx *phy); 2508c2ecf20Sopenharmony_civoid cal_camerarx_ppi_disable(struct cal_camerarx *phy); 2518c2ecf20Sopenharmony_civoid cal_camerarx_i913_errata(struct cal_camerarx *phy); 2528c2ecf20Sopenharmony_cistruct cal_camerarx *cal_camerarx_create(struct cal_dev *cal, 2538c2ecf20Sopenharmony_ci unsigned int instance); 2548c2ecf20Sopenharmony_civoid cal_camerarx_destroy(struct cal_camerarx *phy); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_civoid cal_ctx_csi2_config(struct cal_ctx *ctx); 2578c2ecf20Sopenharmony_civoid cal_ctx_pix_proc_config(struct cal_ctx *ctx); 2588c2ecf20Sopenharmony_civoid cal_ctx_wr_dma_config(struct cal_ctx *ctx, unsigned int width, 2598c2ecf20Sopenharmony_ci unsigned int height); 2608c2ecf20Sopenharmony_civoid cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ciint cal_ctx_v4l2_register(struct cal_ctx *ctx); 2638c2ecf20Sopenharmony_civoid cal_ctx_v4l2_unregister(struct cal_ctx *ctx); 2648c2ecf20Sopenharmony_ciint cal_ctx_v4l2_init(struct cal_ctx *ctx); 2658c2ecf20Sopenharmony_civoid cal_ctx_v4l2_cleanup(struct cal_ctx *ctx); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci#endif /* __TI_CAL_H__ */ 268