Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

-8530
-62
Documentation/admin-guide/media/omap4_camera.rst
··· 1 - .. SPDX-License-Identifier: GPL-2.0 2 - 3 - OMAP4 ISS Driver 4 - ================ 5 - 6 - Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 7 - 8 - Copyright (C) 2012, Texas Instruments 9 - 10 - Introduction 11 - ------------ 12 - 13 - The OMAP44XX family of chips contains the Imaging SubSystem (a.k.a. ISS), 14 - Which contains several components that can be categorized in 3 big groups: 15 - 16 - - Interfaces (2 Interfaces: CSI2-A & CSI2-B/CCP2) 17 - - ISP (Image Signal Processor) 18 - - SIMCOP (Still Image Coprocessor) 19 - 20 - For more information, please look in [#f1]_ for latest version of: 21 - "OMAP4430 Multimedia Device Silicon Revision 2.x" 22 - 23 - As of Revision AB, the ISS is described in detail in section 8. 24 - 25 - This driver is supporting **only** the CSI2-A/B interfaces for now. 26 - 27 - It makes use of the Media Controller framework [#f2]_, and inherited most of the 28 - code from OMAP3 ISP driver (found under drivers/media/platform/ti/omap3isp/\*), 29 - except that it doesn't need an IOMMU now for ISS buffers memory mapping. 30 - 31 - Supports usage of MMAP buffers only (for now). 32 - 33 - Tested platforms 34 - ---------------- 35 - 36 - - OMAP4430SDP, w/ ES2.1 GP & SEVM4430-CAM-V1-0 (Contains IMX060 & OV5640, in 37 - which only the last one is supported, outputting YUV422 frames). 38 - 39 - - TI Blaze MDP, w/ OMAP4430 ES2.2 EMU (Contains 1 IMX060 & 2 OV5650 sensors, in 40 - which only the OV5650 are supported, outputting RAW10 frames). 41 - 42 - - PandaBoard, Rev. A2, w/ OMAP4430 ES2.1 GP & OV adapter board, tested with 43 - following sensors: 44 - * OV5640 45 - * OV5650 46 - 47 - - Tested on mainline kernel: 48 - 49 - http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=summary 50 - 51 - Tag: v3.3 (commit c16fa4f2ad19908a47c63d8fa436a1178438c7e7) 52 - 53 - File list 54 - --------- 55 - drivers/staging/media/omap4iss/ 56 - include/linux/platform_data/media/omap4iss.h 57 - 58 - References 59 - ---------- 60 - 61 - .. [#f1] http://focus.ti.com/general/docs/wtbu/wtbudocumentcenter.tsp?navigationId=12037&templateId=6123#62 62 - .. [#f2] http://lwn.net/Articles/420485/
-1
Documentation/admin-guide/media/v4l-drivers.rst
··· 20 20 ivtv 21 21 mgb4 22 22 omap3isp 23 - omap4_camera 24 23 philips 25 24 qcom_camss 26 25 raspberrypi-pisp-be
-8
MAINTAINERS
··· 16932 16932 F: Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml 16933 16933 F: drivers/i2c/busses/i2c-omap.c 16934 16934 16935 - OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS) 16936 - M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> 16937 - L: linux-media@vger.kernel.org 16938 - S: Maintained 16939 - F: Documentation/devicetree/bindings/media/ti,omap3isp.txt 16940 - F: drivers/media/platform/ti/omap3isp/ 16941 - F: drivers/staging/media/omap4iss/ 16942 - 16943 16935 OMAP MMC SUPPORT 16944 16936 M: Aaro Koskinen <aaro.koskinen@iki.fi> 16945 16937 L: linux-omap@vger.kernel.org
-2
drivers/staging/media/Kconfig
··· 32 32 33 33 source "drivers/staging/media/meson/vdec/Kconfig" 34 34 35 - source "drivers/staging/media/omap4iss/Kconfig" 36 - 37 35 source "drivers/staging/media/rkvdec/Kconfig" 38 36 39 37 source "drivers/staging/media/starfive/Kconfig"
-1
drivers/staging/media/Makefile
··· 4 4 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/ 5 5 obj-$(CONFIG_VIDEO_MAX96712) += max96712/ 6 6 obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/ 7 - obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ 8 7 obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/ 9 8 obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive/ 10 9 obj-$(CONFIG_VIDEO_SUNXI) += sunxi/
-12
drivers/staging/media/omap4iss/Kconfig
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - 3 - config VIDEO_OMAP4 4 - tristate "OMAP 4 Camera support" 5 - depends on VIDEO_DEV && I2C 6 - depends on ARCH_OMAP4 || COMPILE_TEST 7 - select MEDIA_CONTROLLER 8 - select VIDEO_V4L2_SUBDEV_API 9 - select MFD_SYSCON 10 - select VIDEOBUF2_DMA_CONTIG 11 - help 12 - Driver for an OMAP 4 ISS controller.
-9
drivers/staging/media/omap4iss/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - # 3 - # Makefile for OMAP4 ISS driver 4 - # 5 - 6 - omap4-iss-objs += \ 7 - iss.o iss_csi2.o iss_csiphy.o iss_ipipeif.o iss_ipipe.o iss_resizer.o iss_video.o 8 - 9 - obj-$(CONFIG_VIDEO_OMAP4) += omap4-iss.o
-3
drivers/staging/media/omap4iss/TODO
··· 1 - * Fix FIFO/buffer overflows and underflows 2 - * Replace dummy resizer code with a real implementation 3 - * Fix checkpatch errors and warnings
-1354
drivers/staging/media/omap4iss/iss.c
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver 4 - * 5 - * Copyright (C) 2012, Texas Instruments 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #include <linux/clk.h> 11 - #include <linux/delay.h> 12 - #include <linux/device.h> 13 - #include <linux/dma-mapping.h> 14 - #include <linux/i2c.h> 15 - #include <linux/interrupt.h> 16 - #include <linux/mfd/syscon.h> 17 - #include <linux/module.h> 18 - #include <linux/platform_device.h> 19 - #include <linux/slab.h> 20 - #include <linux/sched.h> 21 - #include <linux/vmalloc.h> 22 - 23 - #include <media/v4l2-common.h> 24 - #include <media/v4l2-device.h> 25 - #include <media/v4l2-ctrls.h> 26 - 27 - #include "iss.h" 28 - #include "iss_regs.h" 29 - 30 - #define ISS_PRINT_REGISTER(iss, name)\ 31 - dev_dbg(iss->dev, "###ISS " #name "=0x%08x\n", \ 32 - iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_##name)) 33 - 34 - static void iss_print_status(struct iss_device *iss) 35 - { 36 - dev_dbg(iss->dev, "-------------ISS HL Register dump-------------\n"); 37 - 38 - ISS_PRINT_REGISTER(iss, HL_REVISION); 39 - ISS_PRINT_REGISTER(iss, HL_SYSCONFIG); 40 - ISS_PRINT_REGISTER(iss, HL_IRQSTATUS(5)); 41 - ISS_PRINT_REGISTER(iss, HL_IRQENABLE_SET(5)); 42 - ISS_PRINT_REGISTER(iss, HL_IRQENABLE_CLR(5)); 43 - ISS_PRINT_REGISTER(iss, CTRL); 44 - ISS_PRINT_REGISTER(iss, CLKCTRL); 45 - ISS_PRINT_REGISTER(iss, CLKSTAT); 46 - 47 - dev_dbg(iss->dev, "-----------------------------------------------\n"); 48 - } 49 - 50 - /* 51 - * omap4iss_flush - Post pending L3 bus writes by doing a register readback 52 - * @iss: OMAP4 ISS device 53 - * 54 - * In order to force posting of pending writes, we need to write and 55 - * readback the same register, in this case the revision register. 56 - * 57 - * See this link for reference: 58 - * https://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html 59 - */ 60 - static void omap4iss_flush(struct iss_device *iss) 61 - { 62 - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION, 0); 63 - iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION); 64 - } 65 - 66 - /* 67 - * iss_isp_enable_interrupts - Enable ISS ISP interrupts. 68 - * @iss: OMAP4 ISS device 69 - */ 70 - static void omap4iss_isp_enable_interrupts(struct iss_device *iss) 71 - { 72 - static const u32 isp_irq = ISP5_IRQ_OCP_ERR | 73 - ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | 74 - ISP5_IRQ_RSZ_FIFO_OVF | 75 - ISP5_IRQ_RSZ_INT_DMA | 76 - ISP5_IRQ_ISIF_INT(0); 77 - 78 - /* Enable ISP interrupts */ 79 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), isp_irq); 80 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_SET(0), 81 - isp_irq); 82 - } 83 - 84 - /* 85 - * iss_isp_disable_interrupts - Disable ISS interrupts. 86 - * @iss: OMAP4 ISS device 87 - */ 88 - static void omap4iss_isp_disable_interrupts(struct iss_device *iss) 89 - { 90 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_CLR(0), ~0); 91 - } 92 - 93 - /* 94 - * iss_enable_interrupts - Enable ISS interrupts. 95 - * @iss: OMAP4 ISS device 96 - */ 97 - static void iss_enable_interrupts(struct iss_device *iss) 98 - { 99 - static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB 100 - | ISS_HL_IRQ_ISP(0); 101 - 102 - /* Enable HL interrupts */ 103 - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), hl_irq); 104 - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_SET(5), hl_irq); 105 - 106 - if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1]) 107 - omap4iss_isp_enable_interrupts(iss); 108 - } 109 - 110 - /* 111 - * iss_disable_interrupts - Disable ISS interrupts. 112 - * @iss: OMAP4 ISS device 113 - */ 114 - static void iss_disable_interrupts(struct iss_device *iss) 115 - { 116 - if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1]) 117 - omap4iss_isp_disable_interrupts(iss); 118 - 119 - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_CLR(5), ~0); 120 - } 121 - 122 - int omap4iss_get_external_info(struct iss_pipeline *pipe, 123 - struct media_link *link) 124 - { 125 - struct iss_device *iss = 126 - container_of(pipe, struct iss_video, pipe)->iss; 127 - struct v4l2_subdev_format fmt; 128 - struct v4l2_ctrl *ctrl; 129 - int ret; 130 - 131 - if (!pipe->external) 132 - return 0; 133 - 134 - if (pipe->external_rate) 135 - return 0; 136 - 137 - memset(&fmt, 0, sizeof(fmt)); 138 - 139 - fmt.pad = link->source->index; 140 - fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; 141 - ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(link->sink->entity), 142 - pad, get_fmt, NULL, &fmt); 143 - if (ret < 0) 144 - return -EPIPE; 145 - 146 - pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp; 147 - 148 - ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler, 149 - V4L2_CID_PIXEL_RATE); 150 - if (!ctrl) { 151 - dev_warn(iss->dev, "no pixel rate control in subdev %s\n", 152 - pipe->external->name); 153 - return -EPIPE; 154 - } 155 - 156 - pipe->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl); 157 - 158 - return 0; 159 - } 160 - 161 - /* 162 - * Configure the bridge. Valid inputs are 163 - * 164 - * IPIPEIF_INPUT_CSI2A: CSI2a receiver 165 - * IPIPEIF_INPUT_CSI2B: CSI2b receiver 166 - * 167 - * The bridge and lane shifter are configured according to the selected input 168 - * and the ISP platform data. 169 - */ 170 - void omap4iss_configure_bridge(struct iss_device *iss, 171 - enum ipipeif_input_entity input) 172 - { 173 - u32 issctrl_val; 174 - u32 isp5ctrl_val; 175 - 176 - issctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL); 177 - issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK; 178 - issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK; 179 - 180 - isp5ctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL); 181 - 182 - switch (input) { 183 - case IPIPEIF_INPUT_CSI2A: 184 - issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A; 185 - break; 186 - 187 - case IPIPEIF_INPUT_CSI2B: 188 - issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B; 189 - break; 190 - 191 - default: 192 - return; 193 - } 194 - 195 - issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING; 196 - 197 - isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT | ISP5_CTRL_PSYNC_CLK_SEL | 198 - ISP5_CTRL_SYNC_ENABLE; 199 - 200 - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL, issctrl_val); 201 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, isp5ctrl_val); 202 - } 203 - 204 - #ifdef ISS_ISR_DEBUG 205 - static void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) 206 - { 207 - static const char * const name[] = { 208 - "ISP_0", 209 - "ISP_1", 210 - "ISP_2", 211 - "ISP_3", 212 - "CSIA", 213 - "CSIB", 214 - "CCP2_0", 215 - "CCP2_1", 216 - "CCP2_2", 217 - "CCP2_3", 218 - "CBUFF", 219 - "BTE", 220 - "SIMCOP_0", 221 - "SIMCOP_1", 222 - "SIMCOP_2", 223 - "SIMCOP_3", 224 - "CCP2_8", 225 - "HS_VS", 226 - "18", 227 - "19", 228 - "20", 229 - "21", 230 - "22", 231 - "23", 232 - "24", 233 - "25", 234 - "26", 235 - "27", 236 - "28", 237 - "29", 238 - "30", 239 - "31", 240 - }; 241 - unsigned int i; 242 - 243 - dev_dbg(iss->dev, "ISS IRQ: "); 244 - 245 - for (i = 0; i < ARRAY_SIZE(name); i++) { 246 - if ((1 << i) & irqstatus) 247 - pr_cont("%s ", name[i]); 248 - } 249 - pr_cont("\n"); 250 - } 251 - 252 - static void iss_isp_isr_dbg(struct iss_device *iss, u32 irqstatus) 253 - { 254 - static const char * const name[] = { 255 - "ISIF_0", 256 - "ISIF_1", 257 - "ISIF_2", 258 - "ISIF_3", 259 - "IPIPEREQ", 260 - "IPIPELAST_PIX", 261 - "IPIPEDMA", 262 - "IPIPEBSC", 263 - "IPIPEHST", 264 - "IPIPEIF", 265 - "AEW", 266 - "AF", 267 - "H3A", 268 - "RSZ_REG", 269 - "RSZ_LAST_PIX", 270 - "RSZ_DMA", 271 - "RSZ_CYC_RZA", 272 - "RSZ_CYC_RZB", 273 - "RSZ_FIFO_OVF", 274 - "RSZ_FIFO_IN_BLK_ERR", 275 - "20", 276 - "21", 277 - "RSZ_EOF0", 278 - "RSZ_EOF1", 279 - "H3A_EOF", 280 - "IPIPE_EOF", 281 - "26", 282 - "IPIPE_DPC_INI", 283 - "IPIPE_DPC_RNEW0", 284 - "IPIPE_DPC_RNEW1", 285 - "30", 286 - "OCP_ERR", 287 - }; 288 - unsigned int i; 289 - 290 - dev_dbg(iss->dev, "ISP IRQ: "); 291 - 292 - for (i = 0; i < ARRAY_SIZE(name); i++) { 293 - if ((1 << i) & irqstatus) 294 - pr_cont("%s ", name[i]); 295 - } 296 - pr_cont("\n"); 297 - } 298 - #endif 299 - 300 - /* 301 - * iss_isr - Interrupt Service Routine for ISS module. 302 - * @irq: Not used currently. 303 - * @_iss: Pointer to the OMAP4 ISS device 304 - * 305 - * Handles the corresponding callback if plugged in. 306 - * 307 - * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the 308 - * IRQ wasn't handled. 309 - */ 310 - static irqreturn_t iss_isr(int irq, void *_iss) 311 - { 312 - static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF_IRQ | 313 - ISP5_IRQ_ISIF_INT(0); 314 - static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | 315 - ISP5_IRQ_RSZ_FIFO_OVF | 316 - ISP5_IRQ_RSZ_INT_DMA; 317 - struct iss_device *iss = _iss; 318 - u32 irqstatus; 319 - 320 - irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5)); 321 - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), irqstatus); 322 - 323 - if (irqstatus & ISS_HL_IRQ_CSIA) 324 - omap4iss_csi2_isr(&iss->csi2a); 325 - 326 - if (irqstatus & ISS_HL_IRQ_CSIB) 327 - omap4iss_csi2_isr(&iss->csi2b); 328 - 329 - if (irqstatus & ISS_HL_IRQ_ISP(0)) { 330 - u32 isp_irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, 331 - ISP5_IRQSTATUS(0)); 332 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), 333 - isp_irqstatus); 334 - 335 - if (isp_irqstatus & ISP5_IRQ_OCP_ERR) 336 - dev_dbg(iss->dev, "ISP5 OCP Error!\n"); 337 - 338 - if (isp_irqstatus & ipipeif_events) { 339 - omap4iss_ipipeif_isr(&iss->ipipeif, 340 - isp_irqstatus & ipipeif_events); 341 - } 342 - 343 - if (isp_irqstatus & resizer_events) 344 - omap4iss_resizer_isr(&iss->resizer, 345 - isp_irqstatus & resizer_events); 346 - 347 - #ifdef ISS_ISR_DEBUG 348 - iss_isp_isr_dbg(iss, isp_irqstatus); 349 - #endif 350 - } 351 - 352 - omap4iss_flush(iss); 353 - 354 - #ifdef ISS_ISR_DEBUG 355 - iss_isr_dbg(iss, irqstatus); 356 - #endif 357 - 358 - return IRQ_HANDLED; 359 - } 360 - 361 - static const struct media_device_ops iss_media_ops = { 362 - .link_notify = v4l2_pipeline_link_notify, 363 - }; 364 - 365 - /* ----------------------------------------------------------------------------- 366 - * Pipeline stream management 367 - */ 368 - 369 - /* 370 - * iss_pipeline_disable - Disable streaming on a pipeline 371 - * @pipe: ISS pipeline 372 - * @until: entity at which to stop pipeline walk 373 - * 374 - * Walk the entities chain starting at the pipeline output video node and stop 375 - * all modules in the chain. Wait synchronously for the modules to be stopped if 376 - * necessary. 377 - * 378 - * If the until argument isn't NULL, stop the pipeline walk when reaching the 379 - * until entity. This is used to disable a partially started pipeline due to a 380 - * subdev start error. 381 - */ 382 - static int iss_pipeline_disable(struct iss_pipeline *pipe, 383 - struct media_entity *until) 384 - { 385 - struct iss_device *iss = pipe->output->iss; 386 - struct media_entity *entity; 387 - struct media_pad *pad; 388 - struct v4l2_subdev *subdev; 389 - int failure = 0; 390 - int ret; 391 - 392 - entity = &pipe->output->video.entity; 393 - while (1) { 394 - pad = &entity->pads[0]; 395 - if (!(pad->flags & MEDIA_PAD_FL_SINK)) 396 - break; 397 - 398 - pad = media_pad_remote_pad_first(pad); 399 - if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) 400 - break; 401 - 402 - entity = pad->entity; 403 - if (entity == until) 404 - break; 405 - 406 - subdev = media_entity_to_v4l2_subdev(entity); 407 - ret = v4l2_subdev_call(subdev, video, s_stream, 0); 408 - if (ret < 0) { 409 - dev_warn(iss->dev, "%s: module stop timeout.\n", 410 - subdev->name); 411 - /* If the entity failed to stopped, assume it has 412 - * crashed. Mark it as such, the ISS will be reset when 413 - * applications will release it. 414 - */ 415 - media_entity_enum_set(&iss->crashed, &subdev->entity); 416 - failure = -ETIMEDOUT; 417 - } 418 - } 419 - 420 - return failure; 421 - } 422 - 423 - /* 424 - * iss_pipeline_enable - Enable streaming on a pipeline 425 - * @pipe: ISS pipeline 426 - * @mode: Stream mode (single shot or continuous) 427 - * 428 - * Walk the entities chain starting at the pipeline output video node and start 429 - * all modules in the chain in the given mode. 430 - * 431 - * Return 0 if successful, or the return value of the failed video::s_stream 432 - * operation otherwise. 433 - */ 434 - static int iss_pipeline_enable(struct iss_pipeline *pipe, 435 - enum iss_pipeline_stream_state mode) 436 - { 437 - struct iss_device *iss = pipe->output->iss; 438 - struct media_entity *entity; 439 - struct media_pad *pad; 440 - struct v4l2_subdev *subdev; 441 - unsigned long flags; 442 - int ret; 443 - 444 - /* If one of the entities in the pipeline has crashed it will not work 445 - * properly. Refuse to start streaming in that case. This check must be 446 - * performed before the loop below to avoid starting entities if the 447 - * pipeline won't start anyway (those entities would then likely fail to 448 - * stop, making the problem worse). 449 - */ 450 - if (media_entity_enum_intersects(&pipe->ent_enum, &iss->crashed)) 451 - return -EIO; 452 - 453 - spin_lock_irqsave(&pipe->lock, flags); 454 - pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT); 455 - spin_unlock_irqrestore(&pipe->lock, flags); 456 - 457 - pipe->do_propagation = false; 458 - 459 - mutex_lock(&iss->media_dev.graph_mutex); 460 - 461 - entity = &pipe->output->video.entity; 462 - while (1) { 463 - pad = &entity->pads[0]; 464 - if (!(pad->flags & MEDIA_PAD_FL_SINK)) 465 - break; 466 - 467 - pad = media_pad_remote_pad_first(pad); 468 - if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) 469 - break; 470 - 471 - entity = pad->entity; 472 - subdev = media_entity_to_v4l2_subdev(entity); 473 - 474 - ret = v4l2_subdev_call(subdev, video, s_stream, mode); 475 - if (ret < 0 && ret != -ENOIOCTLCMD) { 476 - iss_pipeline_disable(pipe, entity); 477 - mutex_unlock(&iss->media_dev.graph_mutex); 478 - return ret; 479 - } 480 - 481 - if (subdev == &iss->csi2a.subdev || 482 - subdev == &iss->csi2b.subdev) 483 - pipe->do_propagation = true; 484 - } 485 - 486 - mutex_unlock(&iss->media_dev.graph_mutex); 487 - iss_print_status(pipe->output->iss); 488 - 489 - return 0; 490 - } 491 - 492 - /* 493 - * omap4iss_pipeline_set_stream - Enable/disable streaming on a pipeline 494 - * @pipe: ISS pipeline 495 - * @state: Stream state (stopped, single shot or continuous) 496 - * 497 - * Set the pipeline to the given stream state. Pipelines can be started in 498 - * single-shot or continuous mode. 499 - * 500 - * Return 0 if successful, or the return value of the failed video::s_stream 501 - * operation otherwise. The pipeline state is not updated when the operation 502 - * fails, except when stopping the pipeline. 503 - */ 504 - int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, 505 - enum iss_pipeline_stream_state state) 506 - { 507 - int ret; 508 - 509 - if (state == ISS_PIPELINE_STREAM_STOPPED) 510 - ret = iss_pipeline_disable(pipe, NULL); 511 - else 512 - ret = iss_pipeline_enable(pipe, state); 513 - 514 - if (ret == 0 || state == ISS_PIPELINE_STREAM_STOPPED) 515 - pipe->stream_state = state; 516 - 517 - return ret; 518 - } 519 - 520 - /* 521 - * omap4iss_pipeline_cancel_stream - Cancel stream on a pipeline 522 - * @pipe: ISS pipeline 523 - * 524 - * Cancelling a stream mark all buffers on all video nodes in the pipeline as 525 - * erroneous and makes sure no new buffer can be queued. This function is called 526 - * when a fatal error that prevents any further operation on the pipeline 527 - * occurs. 528 - */ 529 - void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe) 530 - { 531 - if (pipe->input) 532 - omap4iss_video_cancel_stream(pipe->input); 533 - if (pipe->output) 534 - omap4iss_video_cancel_stream(pipe->output); 535 - } 536 - 537 - /* 538 - * iss_pipeline_is_last - Verify if entity has an enabled link to the output 539 - * video node 540 - * @me: ISS module's media entity 541 - * 542 - * Returns 1 if the entity has an enabled link to the output video node or 0 543 - * otherwise. It's true only while pipeline can have no more than one output 544 - * node. 545 - */ 546 - static int iss_pipeline_is_last(struct media_entity *me) 547 - { 548 - struct iss_pipeline *pipe; 549 - struct media_pad *pad; 550 - 551 - pipe = to_iss_pipeline(me); 552 - if (!pipe || pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED) 553 - return 0; 554 - pad = media_pad_remote_pad_first(&pipe->output->pad); 555 - return pad->entity == me; 556 - } 557 - 558 - static int iss_reset(struct iss_device *iss) 559 - { 560 - unsigned int timeout; 561 - 562 - iss_reg_set(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG, 563 - ISS_HL_SYSCONFIG_SOFTRESET); 564 - 565 - timeout = iss_poll_condition_timeout( 566 - !(iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG) & 567 - ISS_HL_SYSCONFIG_SOFTRESET), 1000, 10, 100); 568 - if (timeout) { 569 - dev_err(iss->dev, "ISS reset timeout\n"); 570 - return -ETIMEDOUT; 571 - } 572 - 573 - media_entity_enum_zero(&iss->crashed); 574 - 575 - return 0; 576 - } 577 - 578 - static int iss_isp_reset(struct iss_device *iss) 579 - { 580 - unsigned int timeout; 581 - 582 - /* Fist, ensure that the ISP is IDLE (no transactions happening) */ 583 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG, 584 - ISP5_SYSCONFIG_STANDBYMODE_MASK, 585 - ISP5_SYSCONFIG_STANDBYMODE_SMART); 586 - 587 - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, ISP5_CTRL_MSTANDBY); 588 - 589 - timeout = iss_poll_condition_timeout( 590 - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL) & 591 - ISP5_CTRL_MSTANDBY_WAIT, 1000000, 1000, 1500); 592 - if (timeout) { 593 - dev_err(iss->dev, "ISP5 standby timeout\n"); 594 - return -ETIMEDOUT; 595 - } 596 - 597 - /* Now finally, do the reset */ 598 - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG, 599 - ISP5_SYSCONFIG_SOFTRESET); 600 - 601 - timeout = iss_poll_condition_timeout( 602 - !(iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG) & 603 - ISP5_SYSCONFIG_SOFTRESET), 1000000, 1000, 1500); 604 - if (timeout) { 605 - dev_err(iss->dev, "ISP5 reset timeout\n"); 606 - return -ETIMEDOUT; 607 - } 608 - 609 - return 0; 610 - } 611 - 612 - /* 613 - * iss_module_sync_idle - Helper to sync module with its idle state 614 - * @me: ISS submodule's media entity 615 - * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization 616 - * @stopping: flag which tells module wants to stop 617 - * 618 - * This function checks if ISS submodule needs to wait for next interrupt. If 619 - * yes, makes the caller to sleep while waiting for such event. 620 - */ 621 - int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait, 622 - atomic_t *stopping) 623 - { 624 - struct iss_pipeline *pipe = to_iss_pipeline(me); 625 - struct iss_video *video = pipe->output; 626 - unsigned long flags; 627 - 628 - if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED || 629 - (pipe->stream_state == ISS_PIPELINE_STREAM_SINGLESHOT && 630 - !iss_pipeline_ready(pipe))) 631 - return 0; 632 - 633 - /* 634 - * atomic_set() doesn't include memory barrier on ARM platform for SMP 635 - * scenario. We'll call it here to avoid race conditions. 636 - */ 637 - atomic_set(stopping, 1); 638 - smp_wmb(); 639 - 640 - /* 641 - * If module is the last one, it's writing to memory. In this case, 642 - * it's necessary to check if the module is already paused due to 643 - * DMA queue underrun or if it has to wait for next interrupt to be 644 - * idle. 645 - * If it isn't the last one, the function won't sleep but *stopping 646 - * will still be set to warn next submodule caller's interrupt the 647 - * module wants to be idle. 648 - */ 649 - if (!iss_pipeline_is_last(me)) 650 - return 0; 651 - 652 - spin_lock_irqsave(&video->qlock, flags); 653 - if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { 654 - spin_unlock_irqrestore(&video->qlock, flags); 655 - atomic_set(stopping, 0); 656 - smp_wmb(); 657 - return 0; 658 - } 659 - spin_unlock_irqrestore(&video->qlock, flags); 660 - if (!wait_event_timeout(*wait, !atomic_read(stopping), 661 - msecs_to_jiffies(1000))) { 662 - atomic_set(stopping, 0); 663 - smp_wmb(); 664 - return -ETIMEDOUT; 665 - } 666 - 667 - return 0; 668 - } 669 - 670 - /* 671 - * omap4iss_module_sync_is_stopped - Helper to verify if module was stopping 672 - * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization 673 - * @stopping: flag which tells module wants to stop 674 - * 675 - * This function checks if ISS submodule was stopping. In case of yes, it 676 - * notices the caller by setting stopping to 0 and waking up the wait queue. 677 - * Returns 1 if it was stopping or 0 otherwise. 678 - */ 679 - int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait, 680 - atomic_t *stopping) 681 - { 682 - if (atomic_cmpxchg(stopping, 1, 0)) { 683 - wake_up(wait); 684 - return 1; 685 - } 686 - 687 - return 0; 688 - } 689 - 690 - /* -------------------------------------------------------------------------- 691 - * Clock management 692 - */ 693 - 694 - #define ISS_CLKCTRL_MASK (ISS_CLKCTRL_CSI2_A |\ 695 - ISS_CLKCTRL_CSI2_B |\ 696 - ISS_CLKCTRL_ISP) 697 - 698 - static int __iss_subclk_update(struct iss_device *iss) 699 - { 700 - u32 clk = 0; 701 - int ret = 0, timeout = 1000; 702 - 703 - if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_A) 704 - clk |= ISS_CLKCTRL_CSI2_A; 705 - 706 - if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_B) 707 - clk |= ISS_CLKCTRL_CSI2_B; 708 - 709 - if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP) 710 - clk |= ISS_CLKCTRL_ISP; 711 - 712 - iss_reg_update(iss, OMAP4_ISS_MEM_TOP, ISS_CLKCTRL, 713 - ISS_CLKCTRL_MASK, clk); 714 - 715 - /* Wait for HW assertion */ 716 - while (--timeout > 0) { 717 - udelay(1); 718 - if ((iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CLKSTAT) & 719 - ISS_CLKCTRL_MASK) == clk) 720 - break; 721 - } 722 - 723 - if (!timeout) 724 - ret = -EBUSY; 725 - 726 - return ret; 727 - } 728 - 729 - int omap4iss_subclk_enable(struct iss_device *iss, 730 - enum iss_subclk_resource res) 731 - { 732 - iss->subclk_resources |= res; 733 - 734 - return __iss_subclk_update(iss); 735 - } 736 - 737 - int omap4iss_subclk_disable(struct iss_device *iss, 738 - enum iss_subclk_resource res) 739 - { 740 - iss->subclk_resources &= ~res; 741 - 742 - return __iss_subclk_update(iss); 743 - } 744 - 745 - #define ISS_ISP5_CLKCTRL_MASK (ISP5_CTRL_BL_CLK_ENABLE |\ 746 - ISP5_CTRL_ISIF_CLK_ENABLE |\ 747 - ISP5_CTRL_H3A_CLK_ENABLE |\ 748 - ISP5_CTRL_RSZ_CLK_ENABLE |\ 749 - ISP5_CTRL_IPIPE_CLK_ENABLE |\ 750 - ISP5_CTRL_IPIPEIF_CLK_ENABLE) 751 - 752 - static void __iss_isp_subclk_update(struct iss_device *iss) 753 - { 754 - u32 clk = 0; 755 - 756 - if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_ISIF) 757 - clk |= ISP5_CTRL_ISIF_CLK_ENABLE; 758 - 759 - if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_H3A) 760 - clk |= ISP5_CTRL_H3A_CLK_ENABLE; 761 - 762 - if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_RSZ) 763 - clk |= ISP5_CTRL_RSZ_CLK_ENABLE; 764 - 765 - if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPE) 766 - clk |= ISP5_CTRL_IPIPE_CLK_ENABLE; 767 - 768 - if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPEIF) 769 - clk |= ISP5_CTRL_IPIPEIF_CLK_ENABLE; 770 - 771 - if (clk) 772 - clk |= ISP5_CTRL_BL_CLK_ENABLE; 773 - 774 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, 775 - ISS_ISP5_CLKCTRL_MASK, clk); 776 - } 777 - 778 - void omap4iss_isp_subclk_enable(struct iss_device *iss, 779 - enum iss_isp_subclk_resource res) 780 - { 781 - iss->isp_subclk_resources |= res; 782 - 783 - __iss_isp_subclk_update(iss); 784 - } 785 - 786 - void omap4iss_isp_subclk_disable(struct iss_device *iss, 787 - enum iss_isp_subclk_resource res) 788 - { 789 - iss->isp_subclk_resources &= ~res; 790 - 791 - __iss_isp_subclk_update(iss); 792 - } 793 - 794 - /* 795 - * iss_enable_clocks - Enable ISS clocks 796 - * @iss: OMAP4 ISS device 797 - * 798 - * Return 0 if successful, or clk_enable return value if any of tthem fails. 799 - */ 800 - static int iss_enable_clocks(struct iss_device *iss) 801 - { 802 - int ret; 803 - 804 - ret = clk_enable(iss->iss_fck); 805 - if (ret) { 806 - dev_err(iss->dev, "clk_enable iss_fck failed\n"); 807 - return ret; 808 - } 809 - 810 - ret = clk_enable(iss->iss_ctrlclk); 811 - if (ret) { 812 - dev_err(iss->dev, "clk_enable iss_ctrlclk failed\n"); 813 - clk_disable(iss->iss_fck); 814 - return ret; 815 - } 816 - 817 - return 0; 818 - } 819 - 820 - /* 821 - * iss_disable_clocks - Disable ISS clocks 822 - * @iss: OMAP4 ISS device 823 - */ 824 - static void iss_disable_clocks(struct iss_device *iss) 825 - { 826 - clk_disable(iss->iss_ctrlclk); 827 - clk_disable(iss->iss_fck); 828 - } 829 - 830 - static int iss_get_clocks(struct iss_device *iss) 831 - { 832 - iss->iss_fck = devm_clk_get(iss->dev, "iss_fck"); 833 - if (IS_ERR(iss->iss_fck)) { 834 - dev_err(iss->dev, "Unable to get iss_fck clock info\n"); 835 - return PTR_ERR(iss->iss_fck); 836 - } 837 - 838 - iss->iss_ctrlclk = devm_clk_get(iss->dev, "iss_ctrlclk"); 839 - if (IS_ERR(iss->iss_ctrlclk)) { 840 - dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n"); 841 - return PTR_ERR(iss->iss_ctrlclk); 842 - } 843 - 844 - return 0; 845 - } 846 - 847 - /* 848 - * omap4iss_get - Acquire the ISS resource. 849 - * 850 - * Initializes the clocks for the first acquire. 851 - * 852 - * Increment the reference count on the ISS. If the first reference is taken, 853 - * enable clocks and power-up all submodules. 854 - * 855 - * Return a pointer to the ISS device structure, or NULL if an error occurred. 856 - */ 857 - struct iss_device *omap4iss_get(struct iss_device *iss) 858 - { 859 - struct iss_device *__iss = iss; 860 - 861 - if (!iss) 862 - return NULL; 863 - 864 - mutex_lock(&iss->iss_mutex); 865 - if (iss->ref_count > 0) 866 - goto out; 867 - 868 - if (iss_enable_clocks(iss) < 0) { 869 - __iss = NULL; 870 - goto out; 871 - } 872 - 873 - iss_enable_interrupts(iss); 874 - 875 - out: 876 - if (__iss) 877 - iss->ref_count++; 878 - mutex_unlock(&iss->iss_mutex); 879 - 880 - return __iss; 881 - } 882 - 883 - /* 884 - * omap4iss_put - Release the ISS 885 - * 886 - * Decrement the reference count on the ISS. If the last reference is released, 887 - * power-down all submodules, disable clocks and free temporary buffers. 888 - */ 889 - void omap4iss_put(struct iss_device *iss) 890 - { 891 - if (!iss) 892 - return; 893 - 894 - mutex_lock(&iss->iss_mutex); 895 - WARN_ON(iss->ref_count == 0); 896 - if (--iss->ref_count == 0) { 897 - iss_disable_interrupts(iss); 898 - /* Reset the ISS if an entity has failed to stop. This is the 899 - * only way to recover from such conditions, although it would 900 - * be worth investigating whether resetting the ISP only can't 901 - * fix the problem in some cases. 902 - */ 903 - if (!media_entity_enum_empty(&iss->crashed)) 904 - iss_reset(iss); 905 - iss_disable_clocks(iss); 906 - } 907 - mutex_unlock(&iss->iss_mutex); 908 - } 909 - 910 - static int iss_map_mem_resource(struct platform_device *pdev, 911 - struct iss_device *iss, 912 - enum iss_mem_resources res) 913 - { 914 - iss->regs[res] = devm_platform_ioremap_resource(pdev, res); 915 - 916 - return PTR_ERR_OR_ZERO(iss->regs[res]); 917 - } 918 - 919 - static void iss_unregister_entities(struct iss_device *iss) 920 - { 921 - omap4iss_resizer_unregister_entities(&iss->resizer); 922 - omap4iss_ipipe_unregister_entities(&iss->ipipe); 923 - omap4iss_ipipeif_unregister_entities(&iss->ipipeif); 924 - omap4iss_csi2_unregister_entities(&iss->csi2a); 925 - omap4iss_csi2_unregister_entities(&iss->csi2b); 926 - 927 - v4l2_device_unregister(&iss->v4l2_dev); 928 - media_device_unregister(&iss->media_dev); 929 - } 930 - 931 - /* 932 - * iss_register_subdev_group - Register a group of subdevices 933 - * @iss: OMAP4 ISS device 934 - * @board_info: I2C subdevs board information array 935 - * 936 - * Register all I2C subdevices in the board_info array. The array must be 937 - * terminated by a NULL entry, and the first entry must be the sensor. 938 - * 939 - * Return a pointer to the sensor media entity if it has been successfully 940 - * registered, or NULL otherwise. 941 - */ 942 - static struct v4l2_subdev * 943 - iss_register_subdev_group(struct iss_device *iss, 944 - struct iss_subdev_i2c_board_info *board_info) 945 - { 946 - struct v4l2_subdev *sensor = NULL; 947 - unsigned int first; 948 - 949 - if (!board_info->board_info) 950 - return NULL; 951 - 952 - for (first = 1; board_info->board_info; ++board_info, first = 0) { 953 - struct v4l2_subdev *subdev; 954 - struct i2c_adapter *adapter; 955 - 956 - adapter = i2c_get_adapter(board_info->i2c_adapter_id); 957 - if (!adapter) { 958 - dev_err(iss->dev, 959 - "%s: Unable to get I2C adapter %d for device %s\n", 960 - __func__, board_info->i2c_adapter_id, 961 - board_info->board_info->type); 962 - continue; 963 - } 964 - 965 - subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter, 966 - board_info->board_info, NULL); 967 - if (!subdev) { 968 - dev_err(iss->dev, "Unable to register subdev %s\n", 969 - board_info->board_info->type); 970 - continue; 971 - } 972 - 973 - if (first) 974 - sensor = subdev; 975 - } 976 - 977 - return sensor; 978 - } 979 - 980 - static int iss_register_entities(struct iss_device *iss) 981 - { 982 - struct iss_platform_data *pdata = iss->pdata; 983 - struct iss_v4l2_subdevs_group *subdevs; 984 - int ret; 985 - 986 - iss->media_dev.dev = iss->dev; 987 - strscpy(iss->media_dev.model, "TI OMAP4 ISS", 988 - sizeof(iss->media_dev.model)); 989 - iss->media_dev.hw_revision = iss->revision; 990 - iss->media_dev.ops = &iss_media_ops; 991 - ret = media_device_register(&iss->media_dev); 992 - if (ret < 0) { 993 - dev_err(iss->dev, "Media device registration failed (%d)\n", 994 - ret); 995 - return ret; 996 - } 997 - 998 - iss->v4l2_dev.mdev = &iss->media_dev; 999 - ret = v4l2_device_register(iss->dev, &iss->v4l2_dev); 1000 - if (ret < 0) { 1001 - dev_err(iss->dev, "V4L2 device registration failed (%d)\n", 1002 - ret); 1003 - goto done; 1004 - } 1005 - 1006 - /* Register internal entities */ 1007 - ret = omap4iss_csi2_register_entities(&iss->csi2a, &iss->v4l2_dev); 1008 - if (ret < 0) 1009 - goto done; 1010 - 1011 - ret = omap4iss_csi2_register_entities(&iss->csi2b, &iss->v4l2_dev); 1012 - if (ret < 0) 1013 - goto done; 1014 - 1015 - ret = omap4iss_ipipeif_register_entities(&iss->ipipeif, &iss->v4l2_dev); 1016 - if (ret < 0) 1017 - goto done; 1018 - 1019 - ret = omap4iss_ipipe_register_entities(&iss->ipipe, &iss->v4l2_dev); 1020 - if (ret < 0) 1021 - goto done; 1022 - 1023 - ret = omap4iss_resizer_register_entities(&iss->resizer, &iss->v4l2_dev); 1024 - if (ret < 0) 1025 - goto done; 1026 - 1027 - /* Register external entities */ 1028 - for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) { 1029 - struct v4l2_subdev *sensor; 1030 - struct media_entity *input; 1031 - unsigned int flags; 1032 - unsigned int pad; 1033 - 1034 - sensor = iss_register_subdev_group(iss, subdevs->subdevs); 1035 - if (!sensor) 1036 - continue; 1037 - 1038 - sensor->host_priv = subdevs; 1039 - 1040 - /* Connect the sensor to the correct interface module. 1041 - * CSI2a receiver through CSIPHY1, or 1042 - * CSI2b receiver through CSIPHY2 1043 - */ 1044 - switch (subdevs->interface) { 1045 - case ISS_INTERFACE_CSI2A_PHY1: 1046 - input = &iss->csi2a.subdev.entity; 1047 - pad = CSI2_PAD_SINK; 1048 - flags = MEDIA_LNK_FL_IMMUTABLE 1049 - | MEDIA_LNK_FL_ENABLED; 1050 - break; 1051 - 1052 - case ISS_INTERFACE_CSI2B_PHY2: 1053 - input = &iss->csi2b.subdev.entity; 1054 - pad = CSI2_PAD_SINK; 1055 - flags = MEDIA_LNK_FL_IMMUTABLE 1056 - | MEDIA_LNK_FL_ENABLED; 1057 - break; 1058 - 1059 - default: 1060 - dev_err(iss->dev, "invalid interface type %u\n", 1061 - subdevs->interface); 1062 - ret = -EINVAL; 1063 - goto done; 1064 - } 1065 - 1066 - ret = media_create_pad_link(&sensor->entity, 0, input, pad, 1067 - flags); 1068 - if (ret < 0) 1069 - goto done; 1070 - } 1071 - 1072 - ret = v4l2_device_register_subdev_nodes(&iss->v4l2_dev); 1073 - 1074 - done: 1075 - if (ret < 0) 1076 - iss_unregister_entities(iss); 1077 - 1078 - return ret; 1079 - } 1080 - 1081 - /* 1082 - * iss_create_links() - Pads links creation for the subdevices 1083 - * @iss : Pointer to ISS device 1084 - * 1085 - * return negative error code or zero on success 1086 - */ 1087 - static int iss_create_links(struct iss_device *iss) 1088 - { 1089 - int ret; 1090 - 1091 - ret = omap4iss_csi2_create_links(iss); 1092 - if (ret < 0) { 1093 - dev_err(iss->dev, "CSI2 pads links creation failed\n"); 1094 - return ret; 1095 - } 1096 - 1097 - ret = omap4iss_ipipeif_create_links(iss); 1098 - if (ret < 0) { 1099 - dev_err(iss->dev, "ISP IPIPEIF pads links creation failed\n"); 1100 - return ret; 1101 - } 1102 - 1103 - ret = omap4iss_resizer_create_links(iss); 1104 - if (ret < 0) { 1105 - dev_err(iss->dev, "ISP RESIZER pads links creation failed\n"); 1106 - return ret; 1107 - } 1108 - 1109 - /* Connect the submodules. */ 1110 - ret = media_create_pad_link( 1111 - &iss->csi2a.subdev.entity, CSI2_PAD_SOURCE, 1112 - &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); 1113 - if (ret < 0) 1114 - return ret; 1115 - 1116 - ret = media_create_pad_link( 1117 - &iss->csi2b.subdev.entity, CSI2_PAD_SOURCE, 1118 - &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); 1119 - if (ret < 0) 1120 - return ret; 1121 - 1122 - ret = media_create_pad_link( 1123 - &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, 1124 - &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); 1125 - if (ret < 0) 1126 - return ret; 1127 - 1128 - ret = media_create_pad_link( 1129 - &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, 1130 - &iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0); 1131 - if (ret < 0) 1132 - return ret; 1133 - 1134 - ret = media_create_pad_link( 1135 - &iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP, 1136 - &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); 1137 - if (ret < 0) 1138 - return ret; 1139 - 1140 - return 0; 1141 - }; 1142 - 1143 - static void iss_cleanup_modules(struct iss_device *iss) 1144 - { 1145 - omap4iss_csi2_cleanup(iss); 1146 - omap4iss_ipipeif_cleanup(iss); 1147 - omap4iss_ipipe_cleanup(iss); 1148 - omap4iss_resizer_cleanup(iss); 1149 - } 1150 - 1151 - static int iss_initialize_modules(struct iss_device *iss) 1152 - { 1153 - int ret; 1154 - 1155 - ret = omap4iss_csiphy_init(iss); 1156 - if (ret < 0) { 1157 - dev_err(iss->dev, "CSI PHY initialization failed\n"); 1158 - goto error_csiphy; 1159 - } 1160 - 1161 - ret = omap4iss_csi2_init(iss); 1162 - if (ret < 0) { 1163 - dev_err(iss->dev, "CSI2 initialization failed\n"); 1164 - goto error_csi2; 1165 - } 1166 - 1167 - ret = omap4iss_ipipeif_init(iss); 1168 - if (ret < 0) { 1169 - dev_err(iss->dev, "ISP IPIPEIF initialization failed\n"); 1170 - goto error_ipipeif; 1171 - } 1172 - 1173 - ret = omap4iss_ipipe_init(iss); 1174 - if (ret < 0) { 1175 - dev_err(iss->dev, "ISP IPIPE initialization failed\n"); 1176 - goto error_ipipe; 1177 - } 1178 - 1179 - ret = omap4iss_resizer_init(iss); 1180 - if (ret < 0) { 1181 - dev_err(iss->dev, "ISP RESIZER initialization failed\n"); 1182 - goto error_resizer; 1183 - } 1184 - 1185 - return 0; 1186 - 1187 - error_resizer: 1188 - omap4iss_ipipe_cleanup(iss); 1189 - error_ipipe: 1190 - omap4iss_ipipeif_cleanup(iss); 1191 - error_ipipeif: 1192 - omap4iss_csi2_cleanup(iss); 1193 - error_csi2: 1194 - error_csiphy: 1195 - return ret; 1196 - } 1197 - 1198 - static int iss_probe(struct platform_device *pdev) 1199 - { 1200 - struct iss_platform_data *pdata = pdev->dev.platform_data; 1201 - struct iss_device *iss; 1202 - unsigned int i; 1203 - int ret; 1204 - 1205 - if (!pdata) 1206 - return -EINVAL; 1207 - 1208 - iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL); 1209 - if (!iss) 1210 - return -ENOMEM; 1211 - 1212 - mutex_init(&iss->iss_mutex); 1213 - 1214 - iss->dev = &pdev->dev; 1215 - iss->pdata = pdata; 1216 - 1217 - iss->raw_dmamask = DMA_BIT_MASK(32); 1218 - iss->dev->dma_mask = &iss->raw_dmamask; 1219 - iss->dev->coherent_dma_mask = DMA_BIT_MASK(32); 1220 - 1221 - platform_set_drvdata(pdev, iss); 1222 - 1223 - /* 1224 - * TODO: When implementing DT support switch to syscon regmap lookup by 1225 - * phandle. 1226 - */ 1227 - iss->syscon = syscon_regmap_lookup_by_compatible("syscon"); 1228 - if (IS_ERR(iss->syscon)) { 1229 - ret = PTR_ERR(iss->syscon); 1230 - goto error; 1231 - } 1232 - 1233 - /* Clocks */ 1234 - ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP); 1235 - if (ret < 0) 1236 - goto error; 1237 - 1238 - ret = iss_get_clocks(iss); 1239 - if (ret < 0) 1240 - goto error; 1241 - 1242 - if (!omap4iss_get(iss)) { 1243 - ret = -EINVAL; 1244 - goto error; 1245 - } 1246 - 1247 - ret = iss_reset(iss); 1248 - if (ret < 0) 1249 - goto error_iss; 1250 - 1251 - iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION); 1252 - dev_info(iss->dev, "Revision %08x found\n", iss->revision); 1253 - 1254 - for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) { 1255 - ret = iss_map_mem_resource(pdev, iss, i); 1256 - if (ret) 1257 - goto error_iss; 1258 - } 1259 - 1260 - /* Configure BTE BW_LIMITER field to max recommended value (1 GB) */ 1261 - iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL, 1262 - BTE_CTRL_BW_LIMITER_MASK, 1263 - 18 << BTE_CTRL_BW_LIMITER_SHIFT); 1264 - 1265 - /* Perform ISP reset */ 1266 - ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP); 1267 - if (ret < 0) 1268 - goto error_iss; 1269 - 1270 - ret = iss_isp_reset(iss); 1271 - if (ret < 0) 1272 - goto error_iss; 1273 - 1274 - dev_info(iss->dev, "ISP Revision %08x found\n", 1275 - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION)); 1276 - 1277 - /* Interrupt */ 1278 - ret = platform_get_irq(pdev, 0); 1279 - if (ret <= 0) { 1280 - ret = -ENODEV; 1281 - goto error_iss; 1282 - } 1283 - iss->irq_num = ret; 1284 - 1285 - if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED, 1286 - "OMAP4 ISS", iss)) { 1287 - dev_err(iss->dev, "Unable to request IRQ\n"); 1288 - ret = -EINVAL; 1289 - goto error_iss; 1290 - } 1291 - 1292 - /* Entities */ 1293 - ret = iss_initialize_modules(iss); 1294 - if (ret < 0) 1295 - goto error_iss; 1296 - 1297 - ret = iss_register_entities(iss); 1298 - if (ret < 0) 1299 - goto error_modules; 1300 - 1301 - ret = media_entity_enum_init(&iss->crashed, &iss->media_dev); 1302 - if (ret) 1303 - goto error_entities; 1304 - 1305 - ret = iss_create_links(iss); 1306 - if (ret < 0) 1307 - goto error_entities; 1308 - 1309 - omap4iss_put(iss); 1310 - 1311 - return 0; 1312 - 1313 - error_entities: 1314 - iss_unregister_entities(iss); 1315 - media_entity_enum_cleanup(&iss->crashed); 1316 - error_modules: 1317 - iss_cleanup_modules(iss); 1318 - error_iss: 1319 - omap4iss_put(iss); 1320 - error: 1321 - mutex_destroy(&iss->iss_mutex); 1322 - 1323 - return ret; 1324 - } 1325 - 1326 - static void iss_remove(struct platform_device *pdev) 1327 - { 1328 - struct iss_device *iss = platform_get_drvdata(pdev); 1329 - 1330 - iss_unregister_entities(iss); 1331 - media_entity_enum_cleanup(&iss->crashed); 1332 - iss_cleanup_modules(iss); 1333 - } 1334 - 1335 - static const struct platform_device_id omap4iss_id_table[] = { 1336 - { "omap4iss", 0 }, 1337 - { }, 1338 - }; 1339 - MODULE_DEVICE_TABLE(platform, omap4iss_id_table); 1340 - 1341 - static struct platform_driver iss_driver = { 1342 - .probe = iss_probe, 1343 - .remove_new = iss_remove, 1344 - .id_table = omap4iss_id_table, 1345 - .driver = { 1346 - .name = "omap4iss", 1347 - }, 1348 - }; 1349 - 1350 - module_platform_driver(iss_driver); 1351 - 1352 - MODULE_DESCRIPTION("TI OMAP4 ISS driver"); 1353 - MODULE_AUTHOR("Sergio Aguirre <sergio.a.aguirre@gmail.com>"); 1354 - MODULE_LICENSE("GPL");
-247
drivers/staging/media/omap4iss/iss.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ */ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver 4 - * 5 - * Copyright (C) 2012 Texas Instruments. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #ifndef _OMAP4_ISS_H_ 11 - #define _OMAP4_ISS_H_ 12 - 13 - #include <media/v4l2-device.h> 14 - #include <media/v4l2-mc.h> 15 - 16 - #include <linux/device.h> 17 - #include <linux/io.h> 18 - #include <linux/platform_device.h> 19 - #include <linux/wait.h> 20 - 21 - #include <linux/platform_data/media/omap4iss.h> 22 - 23 - #include "iss_regs.h" 24 - #include "iss_csiphy.h" 25 - #include "iss_csi2.h" 26 - #include "iss_ipipeif.h" 27 - #include "iss_ipipe.h" 28 - #include "iss_resizer.h" 29 - 30 - struct regmap; 31 - 32 - #define to_iss_device(ptr_module) \ 33 - container_of(ptr_module, struct iss_device, ptr_module) 34 - #define to_device(ptr_module) \ 35 - (to_iss_device(ptr_module)->dev) 36 - 37 - enum iss_mem_resources { 38 - OMAP4_ISS_MEM_TOP, 39 - OMAP4_ISS_MEM_CSI2_A_REGS1, 40 - OMAP4_ISS_MEM_CAMERARX_CORE1, 41 - OMAP4_ISS_MEM_CSI2_B_REGS1, 42 - OMAP4_ISS_MEM_CAMERARX_CORE2, 43 - OMAP4_ISS_MEM_BTE, 44 - OMAP4_ISS_MEM_ISP_SYS1, 45 - OMAP4_ISS_MEM_ISP_RESIZER, 46 - OMAP4_ISS_MEM_ISP_IPIPE, 47 - OMAP4_ISS_MEM_ISP_ISIF, 48 - OMAP4_ISS_MEM_ISP_IPIPEIF, 49 - OMAP4_ISS_MEM_LAST, 50 - }; 51 - 52 - enum iss_subclk_resource { 53 - OMAP4_ISS_SUBCLK_SIMCOP = (1 << 0), 54 - OMAP4_ISS_SUBCLK_ISP = (1 << 1), 55 - OMAP4_ISS_SUBCLK_CSI2_A = (1 << 2), 56 - OMAP4_ISS_SUBCLK_CSI2_B = (1 << 3), 57 - OMAP4_ISS_SUBCLK_CCP2 = (1 << 4), 58 - }; 59 - 60 - enum iss_isp_subclk_resource { 61 - OMAP4_ISS_ISP_SUBCLK_BL = (1 << 0), 62 - OMAP4_ISS_ISP_SUBCLK_ISIF = (1 << 1), 63 - OMAP4_ISS_ISP_SUBCLK_H3A = (1 << 2), 64 - OMAP4_ISS_ISP_SUBCLK_RSZ = (1 << 3), 65 - OMAP4_ISS_ISP_SUBCLK_IPIPE = (1 << 4), 66 - OMAP4_ISS_ISP_SUBCLK_IPIPEIF = (1 << 5), 67 - }; 68 - 69 - /* 70 - * struct iss_reg - Structure for ISS register values. 71 - * @reg: 32-bit Register address. 72 - * @val: 32-bit Register value. 73 - */ 74 - struct iss_reg { 75 - enum iss_mem_resources mmio_range; 76 - u32 reg; 77 - u32 val; 78 - }; 79 - 80 - /* 81 - * struct iss_device - ISS device structure. 82 - * @syscon: Regmap for the syscon register space 83 - * @crashed: Crashed entities 84 - */ 85 - struct iss_device { 86 - struct v4l2_device v4l2_dev; 87 - struct media_device media_dev; 88 - struct device *dev; 89 - u32 revision; 90 - 91 - /* platform HW resources */ 92 - struct iss_platform_data *pdata; 93 - unsigned int irq_num; 94 - 95 - struct resource *res[OMAP4_ISS_MEM_LAST]; 96 - void __iomem *regs[OMAP4_ISS_MEM_LAST]; 97 - struct regmap *syscon; 98 - 99 - u64 raw_dmamask; 100 - 101 - struct mutex iss_mutex; /* For handling ref_count field */ 102 - struct media_entity_enum crashed; 103 - int has_context; 104 - int ref_count; 105 - 106 - struct clk *iss_fck; 107 - struct clk *iss_ctrlclk; 108 - 109 - /* ISS modules */ 110 - struct iss_csi2_device csi2a; 111 - struct iss_csi2_device csi2b; 112 - struct iss_csiphy csiphy1; 113 - struct iss_csiphy csiphy2; 114 - struct iss_ipipeif_device ipipeif; 115 - struct iss_ipipe_device ipipe; 116 - struct iss_resizer_device resizer; 117 - 118 - unsigned int subclk_resources; 119 - unsigned int isp_subclk_resources; 120 - }; 121 - 122 - int omap4iss_get_external_info(struct iss_pipeline *pipe, 123 - struct media_link *link); 124 - 125 - int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait, 126 - atomic_t *stopping); 127 - 128 - int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait, 129 - atomic_t *stopping); 130 - 131 - int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, 132 - enum iss_pipeline_stream_state state); 133 - void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe); 134 - 135 - void omap4iss_configure_bridge(struct iss_device *iss, 136 - enum ipipeif_input_entity input); 137 - 138 - struct iss_device *omap4iss_get(struct iss_device *iss); 139 - void omap4iss_put(struct iss_device *iss); 140 - int omap4iss_subclk_enable(struct iss_device *iss, 141 - enum iss_subclk_resource res); 142 - int omap4iss_subclk_disable(struct iss_device *iss, 143 - enum iss_subclk_resource res); 144 - void omap4iss_isp_subclk_enable(struct iss_device *iss, 145 - enum iss_isp_subclk_resource res); 146 - void omap4iss_isp_subclk_disable(struct iss_device *iss, 147 - enum iss_isp_subclk_resource res); 148 - 149 - int omap4iss_register_entities(struct platform_device *pdev, 150 - struct v4l2_device *v4l2_dev); 151 - void omap4iss_unregister_entities(struct platform_device *pdev); 152 - 153 - /* 154 - * iss_reg_read - Read the value of an OMAP4 ISS register 155 - * @iss: the ISS device 156 - * @res: memory resource in which the register is located 157 - * @offset: register offset in the memory resource 158 - * 159 - * Return the register value. 160 - */ 161 - static inline 162 - u32 iss_reg_read(struct iss_device *iss, enum iss_mem_resources res, 163 - u32 offset) 164 - { 165 - return readl(iss->regs[res] + offset); 166 - } 167 - 168 - /* 169 - * iss_reg_write - Write a value to an OMAP4 ISS register 170 - * @iss: the ISS device 171 - * @res: memory resource in which the register is located 172 - * @offset: register offset in the memory resource 173 - * @value: value to be written 174 - */ 175 - static inline 176 - void iss_reg_write(struct iss_device *iss, enum iss_mem_resources res, 177 - u32 offset, u32 value) 178 - { 179 - writel(value, iss->regs[res] + offset); 180 - } 181 - 182 - /* 183 - * iss_reg_clr - Clear bits in an OMAP4 ISS register 184 - * @iss: the ISS device 185 - * @res: memory resource in which the register is located 186 - * @offset: register offset in the memory resource 187 - * @clr: bit mask to be cleared 188 - */ 189 - static inline 190 - void iss_reg_clr(struct iss_device *iss, enum iss_mem_resources res, 191 - u32 offset, u32 clr) 192 - { 193 - u32 v = iss_reg_read(iss, res, offset); 194 - 195 - iss_reg_write(iss, res, offset, v & ~clr); 196 - } 197 - 198 - /* 199 - * iss_reg_set - Set bits in an OMAP4 ISS register 200 - * @iss: the ISS device 201 - * @res: memory resource in which the register is located 202 - * @offset: register offset in the memory resource 203 - * @set: bit mask to be set 204 - */ 205 - static inline 206 - void iss_reg_set(struct iss_device *iss, enum iss_mem_resources res, 207 - u32 offset, u32 set) 208 - { 209 - u32 v = iss_reg_read(iss, res, offset); 210 - 211 - iss_reg_write(iss, res, offset, v | set); 212 - } 213 - 214 - /* 215 - * iss_reg_update - Clear and set bits in an OMAP4 ISS register 216 - * @iss: the ISS device 217 - * @res: memory resource in which the register is located 218 - * @offset: register offset in the memory resource 219 - * @clr: bit mask to be cleared 220 - * @set: bit mask to be set 221 - * 222 - * Clear the clr mask first and then set the set mask. 223 - */ 224 - static inline 225 - void iss_reg_update(struct iss_device *iss, enum iss_mem_resources res, 226 - u32 offset, u32 clr, u32 set) 227 - { 228 - u32 v = iss_reg_read(iss, res, offset); 229 - 230 - iss_reg_write(iss, res, offset, (v & ~clr) | set); 231 - } 232 - 233 - #define iss_poll_condition_timeout(cond, timeout, min_ival, max_ival) \ 234 - ({ \ 235 - unsigned long __timeout = jiffies + usecs_to_jiffies(timeout); \ 236 - unsigned int __min_ival = (min_ival); \ 237 - unsigned int __max_ival = (max_ival); \ 238 - bool __cond; \ 239 - while (!(__cond = (cond))) { \ 240 - if (time_after(jiffies, __timeout)) \ 241 - break; \ 242 - usleep_range(__min_ival, __max_ival); \ 243 - } \ 244 - !__cond; \ 245 - }) 246 - 247 - #endif /* _OMAP4_ISS_H_ */
-1379
drivers/staging/media/omap4iss/iss_csi2.c
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - CSI PHY module 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #include <linux/delay.h> 11 - #include <media/v4l2-common.h> 12 - #include <linux/v4l2-mediabus.h> 13 - #include <linux/mm.h> 14 - 15 - #include "iss.h" 16 - #include "iss_regs.h" 17 - #include "iss_csi2.h" 18 - 19 - /* 20 - * csi2_if_enable - Enable CSI2 Receiver interface. 21 - * @enable: enable flag 22 - * 23 - */ 24 - static void csi2_if_enable(struct iss_csi2_device *csi2, u8 enable) 25 - { 26 - struct iss_csi2_ctrl_cfg *currctrl = &csi2->ctrl; 27 - 28 - iss_reg_update(csi2->iss, csi2->regs1, CSI2_CTRL, CSI2_CTRL_IF_EN, 29 - enable ? CSI2_CTRL_IF_EN : 0); 30 - 31 - currctrl->if_enable = enable; 32 - } 33 - 34 - /* 35 - * csi2_recv_config - CSI2 receiver module configuration. 36 - * @currctrl: iss_csi2_ctrl_cfg structure 37 - * 38 - */ 39 - static void csi2_recv_config(struct iss_csi2_device *csi2, 40 - struct iss_csi2_ctrl_cfg *currctrl) 41 - { 42 - u32 reg = 0; 43 - 44 - if (currctrl->frame_mode) 45 - reg |= CSI2_CTRL_FRAME; 46 - else 47 - reg &= ~CSI2_CTRL_FRAME; 48 - 49 - if (currctrl->vp_clk_enable) 50 - reg |= CSI2_CTRL_VP_CLK_EN; 51 - else 52 - reg &= ~CSI2_CTRL_VP_CLK_EN; 53 - 54 - if (currctrl->vp_only_enable) 55 - reg |= CSI2_CTRL_VP_ONLY_EN; 56 - else 57 - reg &= ~CSI2_CTRL_VP_ONLY_EN; 58 - 59 - reg &= ~CSI2_CTRL_VP_OUT_CTRL_MASK; 60 - reg |= currctrl->vp_out_ctrl << CSI2_CTRL_VP_OUT_CTRL_SHIFT; 61 - 62 - if (currctrl->ecc_enable) 63 - reg |= CSI2_CTRL_ECC_EN; 64 - else 65 - reg &= ~CSI2_CTRL_ECC_EN; 66 - 67 - /* 68 - * Set MFlag assertion boundaries to: 69 - * Low: 4/8 of FIFO size 70 - * High: 6/8 of FIFO size 71 - */ 72 - reg &= ~(CSI2_CTRL_MFLAG_LEVH_MASK | CSI2_CTRL_MFLAG_LEVL_MASK); 73 - reg |= (2 << CSI2_CTRL_MFLAG_LEVH_SHIFT) | 74 - (4 << CSI2_CTRL_MFLAG_LEVL_SHIFT); 75 - 76 - /* Generation of 16x64-bit bursts (Recommended) */ 77 - reg |= CSI2_CTRL_BURST_SIZE_EXPAND; 78 - 79 - /* Do Non-Posted writes (Recommended) */ 80 - reg |= CSI2_CTRL_NON_POSTED_WRITE; 81 - 82 - /* 83 - * Enforce Little endian for all formats, including: 84 - * YUV4:2:2 8-bit and YUV4:2:0 Legacy 85 - */ 86 - reg |= CSI2_CTRL_ENDIANNESS; 87 - 88 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTRL, reg); 89 - } 90 - 91 - static const unsigned int csi2_input_fmts[] = { 92 - MEDIA_BUS_FMT_SGRBG10_1X10, 93 - MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, 94 - MEDIA_BUS_FMT_SRGGB10_1X10, 95 - MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, 96 - MEDIA_BUS_FMT_SBGGR10_1X10, 97 - MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, 98 - MEDIA_BUS_FMT_SGBRG10_1X10, 99 - MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, 100 - MEDIA_BUS_FMT_SBGGR8_1X8, 101 - MEDIA_BUS_FMT_SGBRG8_1X8, 102 - MEDIA_BUS_FMT_SGRBG8_1X8, 103 - MEDIA_BUS_FMT_SRGGB8_1X8, 104 - MEDIA_BUS_FMT_UYVY8_1X16, 105 - MEDIA_BUS_FMT_YUYV8_1X16, 106 - }; 107 - 108 - /* To set the format on the CSI2 requires a mapping function that takes 109 - * the following inputs: 110 - * - 3 different formats (at this time) 111 - * - 2 destinations (mem, vp+mem) (vp only handled separately) 112 - * - 2 decompression options (on, off) 113 - * Output should be CSI2 frame format code 114 - * Array indices as follows: [format][dest][decompr] 115 - * Not all combinations are valid. 0 means invalid. 116 - */ 117 - static const u16 __csi2_fmt_map[][2][2] = { 118 - /* RAW10 formats */ 119 - { 120 - /* Output to memory */ 121 - { 122 - /* No DPCM decompression */ 123 - CSI2_PIX_FMT_RAW10_EXP16, 124 - /* DPCM decompression */ 125 - 0, 126 - }, 127 - /* Output to both */ 128 - { 129 - /* No DPCM decompression */ 130 - CSI2_PIX_FMT_RAW10_EXP16_VP, 131 - /* DPCM decompression */ 132 - 0, 133 - }, 134 - }, 135 - /* RAW10 DPCM8 formats */ 136 - { 137 - /* Output to memory */ 138 - { 139 - /* No DPCM decompression */ 140 - CSI2_USERDEF_8BIT_DATA1, 141 - /* DPCM decompression */ 142 - CSI2_USERDEF_8BIT_DATA1_DPCM10, 143 - }, 144 - /* Output to both */ 145 - { 146 - /* No DPCM decompression */ 147 - CSI2_PIX_FMT_RAW8_VP, 148 - /* DPCM decompression */ 149 - CSI2_USERDEF_8BIT_DATA1_DPCM10_VP, 150 - }, 151 - }, 152 - /* RAW8 formats */ 153 - { 154 - /* Output to memory */ 155 - { 156 - /* No DPCM decompression */ 157 - CSI2_PIX_FMT_RAW8, 158 - /* DPCM decompression */ 159 - 0, 160 - }, 161 - /* Output to both */ 162 - { 163 - /* No DPCM decompression */ 164 - CSI2_PIX_FMT_RAW8_VP, 165 - /* DPCM decompression */ 166 - 0, 167 - }, 168 - }, 169 - /* YUV422 formats */ 170 - { 171 - /* Output to memory */ 172 - { 173 - /* No DPCM decompression */ 174 - CSI2_PIX_FMT_YUV422_8BIT, 175 - /* DPCM decompression */ 176 - 0, 177 - }, 178 - /* Output to both */ 179 - { 180 - /* No DPCM decompression */ 181 - CSI2_PIX_FMT_YUV422_8BIT_VP16, 182 - /* DPCM decompression */ 183 - 0, 184 - }, 185 - }, 186 - }; 187 - 188 - /* 189 - * csi2_ctx_map_format - Map CSI2 sink media bus format to CSI2 format ID 190 - * @csi2: ISS CSI2 device 191 - * 192 - * Returns CSI2 physical format id 193 - */ 194 - static u16 csi2_ctx_map_format(struct iss_csi2_device *csi2) 195 - { 196 - const struct v4l2_mbus_framefmt *fmt = &csi2->formats[CSI2_PAD_SINK]; 197 - int fmtidx, destidx; 198 - 199 - switch (fmt->code) { 200 - case MEDIA_BUS_FMT_SGRBG10_1X10: 201 - case MEDIA_BUS_FMT_SRGGB10_1X10: 202 - case MEDIA_BUS_FMT_SBGGR10_1X10: 203 - case MEDIA_BUS_FMT_SGBRG10_1X10: 204 - fmtidx = 0; 205 - break; 206 - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: 207 - case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8: 208 - case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8: 209 - case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8: 210 - fmtidx = 1; 211 - break; 212 - case MEDIA_BUS_FMT_SBGGR8_1X8: 213 - case MEDIA_BUS_FMT_SGBRG8_1X8: 214 - case MEDIA_BUS_FMT_SGRBG8_1X8: 215 - case MEDIA_BUS_FMT_SRGGB8_1X8: 216 - fmtidx = 2; 217 - break; 218 - case MEDIA_BUS_FMT_UYVY8_1X16: 219 - case MEDIA_BUS_FMT_YUYV8_1X16: 220 - fmtidx = 3; 221 - break; 222 - default: 223 - WARN(1, "CSI2: pixel format %08x unsupported!\n", 224 - fmt->code); 225 - return 0; 226 - } 227 - 228 - if (!(csi2->output & CSI2_OUTPUT_IPIPEIF) && 229 - !(csi2->output & CSI2_OUTPUT_MEMORY)) { 230 - /* Neither output enabled is a valid combination */ 231 - return CSI2_PIX_FMT_OTHERS; 232 - } 233 - 234 - /* If we need to skip frames at the beginning of the stream disable the 235 - * video port to avoid sending the skipped frames to the IPIPEIF. 236 - */ 237 - destidx = csi2->frame_skip ? 0 : !!(csi2->output & CSI2_OUTPUT_IPIPEIF); 238 - 239 - return __csi2_fmt_map[fmtidx][destidx][csi2->dpcm_decompress]; 240 - } 241 - 242 - /* 243 - * csi2_set_outaddr - Set memory address to save output image 244 - * @csi2: Pointer to ISS CSI2a device. 245 - * @addr: 32-bit memory address aligned on 32 byte boundary. 246 - * 247 - * Sets the memory address where the output will be saved. 248 - * 249 - * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte 250 - * boundary. 251 - */ 252 - static void csi2_set_outaddr(struct iss_csi2_device *csi2, u32 addr) 253 - { 254 - struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[0]; 255 - 256 - ctx->ping_addr = addr; 257 - ctx->pong_addr = addr; 258 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PING_ADDR(ctx->ctxnum), 259 - ctx->ping_addr); 260 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PONG_ADDR(ctx->ctxnum), 261 - ctx->pong_addr); 262 - } 263 - 264 - /* 265 - * is_usr_def_mapping - Checks whether USER_DEF_MAPPING should 266 - * be enabled by CSI2. 267 - * @format_id: mapped format id 268 - * 269 - */ 270 - static inline int is_usr_def_mapping(u32 format_id) 271 - { 272 - return (format_id & 0xf0) == 0x40 ? 1 : 0; 273 - } 274 - 275 - /* 276 - * csi2_ctx_enable - Enable specified CSI2 context 277 - * @ctxnum: Context number, valid between 0 and 7 values. 278 - * @enable: enable 279 - * 280 - */ 281 - static void csi2_ctx_enable(struct iss_csi2_device *csi2, u8 ctxnum, u8 enable) 282 - { 283 - struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum]; 284 - u32 reg; 285 - 286 - reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctxnum)); 287 - 288 - if (enable) { 289 - unsigned int skip = 0; 290 - 291 - if (csi2->frame_skip) 292 - skip = csi2->frame_skip; 293 - else if (csi2->output & CSI2_OUTPUT_MEMORY) 294 - skip = 1; 295 - 296 - reg &= ~CSI2_CTX_CTRL1_COUNT_MASK; 297 - reg |= CSI2_CTX_CTRL1_COUNT_UNLOCK 298 - | (skip << CSI2_CTX_CTRL1_COUNT_SHIFT) 299 - | CSI2_CTX_CTRL1_CTX_EN; 300 - } else { 301 - reg &= ~CSI2_CTX_CTRL1_CTX_EN; 302 - } 303 - 304 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctxnum), reg); 305 - ctx->enabled = enable; 306 - } 307 - 308 - /* 309 - * csi2_ctx_config - CSI2 context configuration. 310 - * @ctx: context configuration 311 - * 312 - */ 313 - static void csi2_ctx_config(struct iss_csi2_device *csi2, 314 - struct iss_csi2_ctx_cfg *ctx) 315 - { 316 - u32 reg = 0; 317 - 318 - ctx->frame = 0; 319 - 320 - /* Set up CSI2_CTx_CTRL1 */ 321 - if (ctx->eof_enabled) 322 - reg = CSI2_CTX_CTRL1_EOF_EN; 323 - 324 - if (ctx->eol_enabled) 325 - reg |= CSI2_CTX_CTRL1_EOL_EN; 326 - 327 - if (ctx->checksum_enabled) 328 - reg |= CSI2_CTX_CTRL1_CS_EN; 329 - 330 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctx->ctxnum), reg); 331 - 332 - /* Set up CSI2_CTx_CTRL2 */ 333 - reg = ctx->virtual_id << CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT; 334 - reg |= ctx->format_id << CSI2_CTX_CTRL2_FORMAT_SHIFT; 335 - 336 - if (ctx->dpcm_decompress && ctx->dpcm_predictor) 337 - reg |= CSI2_CTX_CTRL2_DPCM_PRED; 338 - 339 - if (is_usr_def_mapping(ctx->format_id)) 340 - reg |= 2 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT; 341 - 342 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL2(ctx->ctxnum), reg); 343 - 344 - /* Set up CSI2_CTx_CTRL3 */ 345 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL3(ctx->ctxnum), 346 - ctx->alpha << CSI2_CTX_CTRL3_ALPHA_SHIFT); 347 - 348 - /* Set up CSI2_CTx_DAT_OFST */ 349 - iss_reg_update(csi2->iss, csi2->regs1, CSI2_CTX_DAT_OFST(ctx->ctxnum), 350 - CSI2_CTX_DAT_OFST_MASK, ctx->data_offset); 351 - 352 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PING_ADDR(ctx->ctxnum), 353 - ctx->ping_addr); 354 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PONG_ADDR(ctx->ctxnum), 355 - ctx->pong_addr); 356 - } 357 - 358 - /* 359 - * csi2_timing_config - CSI2 timing configuration. 360 - * @timing: csi2_timing_cfg structure 361 - */ 362 - static void csi2_timing_config(struct iss_csi2_device *csi2, 363 - struct iss_csi2_timing_cfg *timing) 364 - { 365 - u32 reg; 366 - 367 - reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_TIMING); 368 - 369 - if (timing->force_rx_mode) 370 - reg |= CSI2_TIMING_FORCE_RX_MODE_IO1; 371 - else 372 - reg &= ~CSI2_TIMING_FORCE_RX_MODE_IO1; 373 - 374 - if (timing->stop_state_16x) 375 - reg |= CSI2_TIMING_STOP_STATE_X16_IO1; 376 - else 377 - reg &= ~CSI2_TIMING_STOP_STATE_X16_IO1; 378 - 379 - if (timing->stop_state_4x) 380 - reg |= CSI2_TIMING_STOP_STATE_X4_IO1; 381 - else 382 - reg &= ~CSI2_TIMING_STOP_STATE_X4_IO1; 383 - 384 - reg &= ~CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK; 385 - reg |= timing->stop_state_counter << 386 - CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT; 387 - 388 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_TIMING, reg); 389 - } 390 - 391 - /* 392 - * csi2_irq_ctx_set - Enables CSI2 Context IRQs. 393 - * @enable: Enable/disable CSI2 Context interrupts 394 - */ 395 - static void csi2_irq_ctx_set(struct iss_csi2_device *csi2, int enable) 396 - { 397 - const u32 mask = CSI2_CTX_IRQ_FE | CSI2_CTX_IRQ_FS; 398 - int i; 399 - 400 - for (i = 0; i < 8; i++) { 401 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(i), 402 - mask); 403 - if (enable) 404 - iss_reg_set(csi2->iss, csi2->regs1, 405 - CSI2_CTX_IRQENABLE(i), mask); 406 - else 407 - iss_reg_clr(csi2->iss, csi2->regs1, 408 - CSI2_CTX_IRQENABLE(i), mask); 409 - } 410 - } 411 - 412 - /* 413 - * csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs. 414 - * @enable: Enable/disable CSI2 ComplexIO #1 interrupts 415 - */ 416 - static void csi2_irq_complexio1_set(struct iss_csi2_device *csi2, int enable) 417 - { 418 - u32 reg; 419 - 420 - reg = CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT | 421 - CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER | 422 - CSI2_COMPLEXIO_IRQ_STATEULPM5 | 423 - CSI2_COMPLEXIO_IRQ_ERRCONTROL5 | 424 - CSI2_COMPLEXIO_IRQ_ERRESC5 | 425 - CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 | 426 - CSI2_COMPLEXIO_IRQ_ERRSOTHS5 | 427 - CSI2_COMPLEXIO_IRQ_STATEULPM4 | 428 - CSI2_COMPLEXIO_IRQ_ERRCONTROL4 | 429 - CSI2_COMPLEXIO_IRQ_ERRESC4 | 430 - CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 | 431 - CSI2_COMPLEXIO_IRQ_ERRSOTHS4 | 432 - CSI2_COMPLEXIO_IRQ_STATEULPM3 | 433 - CSI2_COMPLEXIO_IRQ_ERRCONTROL3 | 434 - CSI2_COMPLEXIO_IRQ_ERRESC3 | 435 - CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 | 436 - CSI2_COMPLEXIO_IRQ_ERRSOTHS3 | 437 - CSI2_COMPLEXIO_IRQ_STATEULPM2 | 438 - CSI2_COMPLEXIO_IRQ_ERRCONTROL2 | 439 - CSI2_COMPLEXIO_IRQ_ERRESC2 | 440 - CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 | 441 - CSI2_COMPLEXIO_IRQ_ERRSOTHS2 | 442 - CSI2_COMPLEXIO_IRQ_STATEULPM1 | 443 - CSI2_COMPLEXIO_IRQ_ERRCONTROL1 | 444 - CSI2_COMPLEXIO_IRQ_ERRESC1 | 445 - CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 | 446 - CSI2_COMPLEXIO_IRQ_ERRSOTHS1; 447 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQSTATUS, reg); 448 - if (enable) 449 - iss_reg_set(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQENABLE, 450 - reg); 451 - else 452 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQENABLE, 453 - 0); 454 - } 455 - 456 - /* 457 - * csi2_irq_status_set - Enables CSI2 Status IRQs. 458 - * @enable: Enable/disable CSI2 Status interrupts 459 - */ 460 - static void csi2_irq_status_set(struct iss_csi2_device *csi2, int enable) 461 - { 462 - u32 reg; 463 - 464 - reg = CSI2_IRQ_OCP_ERR | 465 - CSI2_IRQ_SHORT_PACKET | 466 - CSI2_IRQ_ECC_CORRECTION | 467 - CSI2_IRQ_ECC_NO_CORRECTION | 468 - CSI2_IRQ_COMPLEXIO_ERR | 469 - CSI2_IRQ_FIFO_OVF | 470 - CSI2_IRQ_CONTEXT0; 471 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQSTATUS, reg); 472 - if (enable) 473 - iss_reg_set(csi2->iss, csi2->regs1, CSI2_IRQENABLE, reg); 474 - else 475 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQENABLE, 0); 476 - } 477 - 478 - /* 479 - * omap4iss_csi2_reset - Resets the CSI2 module. 480 - * 481 - * Must be called with the phy lock held. 482 - * 483 - * Returns 0 if successful, or -EBUSY if power command didn't respond. 484 - */ 485 - int omap4iss_csi2_reset(struct iss_csi2_device *csi2) 486 - { 487 - unsigned int timeout; 488 - 489 - if (!csi2->available) 490 - return -ENODEV; 491 - 492 - if (csi2->phy->phy_in_use) 493 - return -EBUSY; 494 - 495 - iss_reg_set(csi2->iss, csi2->regs1, CSI2_SYSCONFIG, 496 - CSI2_SYSCONFIG_SOFT_RESET); 497 - 498 - timeout = iss_poll_condition_timeout( 499 - iss_reg_read(csi2->iss, csi2->regs1, CSI2_SYSSTATUS) & 500 - CSI2_SYSSTATUS_RESET_DONE, 500, 100, 200); 501 - if (timeout) { 502 - dev_err(csi2->iss->dev, "CSI2: Soft reset timeout!\n"); 503 - return -EBUSY; 504 - } 505 - 506 - iss_reg_set(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_CFG, 507 - CSI2_COMPLEXIO_CFG_RESET_CTRL); 508 - 509 - timeout = iss_poll_condition_timeout( 510 - iss_reg_read(csi2->iss, csi2->phy->phy_regs, REGISTER1) & 511 - REGISTER1_RESET_DONE_CTRLCLK, 10000, 100, 500); 512 - if (timeout) { 513 - dev_err(csi2->iss->dev, "CSI2: CSI2_96M_FCLK reset timeout!\n"); 514 - return -EBUSY; 515 - } 516 - 517 - iss_reg_update(csi2->iss, csi2->regs1, CSI2_SYSCONFIG, 518 - CSI2_SYSCONFIG_MSTANDBY_MODE_MASK | 519 - CSI2_SYSCONFIG_AUTO_IDLE, 520 - CSI2_SYSCONFIG_MSTANDBY_MODE_NO); 521 - 522 - return 0; 523 - } 524 - 525 - static int csi2_configure(struct iss_csi2_device *csi2) 526 - { 527 - const struct iss_v4l2_subdevs_group *pdata; 528 - struct iss_csi2_timing_cfg *timing = &csi2->timing[0]; 529 - struct v4l2_subdev *sensor; 530 - struct media_pad *pad; 531 - 532 - /* 533 - * CSI2 fields that can be updated while the context has 534 - * been enabled or the interface has been enabled are not 535 - * updated dynamically currently. So we do not allow to 536 - * reconfigure if either has been enabled 537 - */ 538 - if (csi2->contexts[0].enabled || csi2->ctrl.if_enable) 539 - return -EBUSY; 540 - 541 - pad = media_pad_remote_pad_first(&csi2->pads[CSI2_PAD_SINK]); 542 - sensor = media_entity_to_v4l2_subdev(pad->entity); 543 - pdata = sensor->host_priv; 544 - 545 - csi2->frame_skip = 0; 546 - v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip); 547 - 548 - csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div; 549 - csi2->ctrl.frame_mode = ISS_CSI2_FRAME_IMMEDIATE; 550 - csi2->ctrl.ecc_enable = pdata->bus.csi2.crc; 551 - 552 - timing->force_rx_mode = 1; 553 - timing->stop_state_16x = 1; 554 - timing->stop_state_4x = 1; 555 - timing->stop_state_counter = 0x1ff; 556 - 557 - /* 558 - * The CSI2 receiver can't do any format conversion except DPCM 559 - * decompression, so every set_format call configures both pads 560 - * and enables DPCM decompression as a special case: 561 - */ 562 - if (csi2->formats[CSI2_PAD_SINK].code != 563 - csi2->formats[CSI2_PAD_SOURCE].code) 564 - csi2->dpcm_decompress = true; 565 - else 566 - csi2->dpcm_decompress = false; 567 - 568 - csi2->contexts[0].format_id = csi2_ctx_map_format(csi2); 569 - 570 - if (csi2->video_out.bpl_padding == 0) 571 - csi2->contexts[0].data_offset = 0; 572 - else 573 - csi2->contexts[0].data_offset = csi2->video_out.bpl_value; 574 - 575 - /* 576 - * Enable end of frame and end of line signals generation for 577 - * context 0. These signals are generated from CSI2 receiver to 578 - * qualify the last pixel of a frame and the last pixel of a line. 579 - * Without enabling the signals CSI2 receiver writes data to memory 580 - * beyond buffer size and/or data line offset is not handled correctly. 581 - */ 582 - csi2->contexts[0].eof_enabled = 1; 583 - csi2->contexts[0].eol_enabled = 1; 584 - 585 - csi2_irq_complexio1_set(csi2, 1); 586 - csi2_irq_ctx_set(csi2, 1); 587 - csi2_irq_status_set(csi2, 1); 588 - 589 - /* Set configuration (timings, format and links) */ 590 - csi2_timing_config(csi2, timing); 591 - csi2_recv_config(csi2, &csi2->ctrl); 592 - csi2_ctx_config(csi2, &csi2->contexts[0]); 593 - 594 - return 0; 595 - } 596 - 597 - /* 598 - * csi2_print_status - Prints CSI2 debug information. 599 - */ 600 - #define CSI2_PRINT_REGISTER(iss, regs, name)\ 601 - dev_dbg(iss->dev, "###CSI2 " #name "=0x%08x\n", \ 602 - iss_reg_read(iss, regs, CSI2_##name)) 603 - 604 - static void csi2_print_status(struct iss_csi2_device *csi2) 605 - { 606 - struct iss_device *iss = csi2->iss; 607 - 608 - if (!csi2->available) 609 - return; 610 - 611 - dev_dbg(iss->dev, "-------------CSI2 Register dump-------------\n"); 612 - 613 - CSI2_PRINT_REGISTER(iss, csi2->regs1, SYSCONFIG); 614 - CSI2_PRINT_REGISTER(iss, csi2->regs1, SYSSTATUS); 615 - CSI2_PRINT_REGISTER(iss, csi2->regs1, IRQENABLE); 616 - CSI2_PRINT_REGISTER(iss, csi2->regs1, IRQSTATUS); 617 - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTRL); 618 - CSI2_PRINT_REGISTER(iss, csi2->regs1, DBG_H); 619 - CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_CFG); 620 - CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_IRQSTATUS); 621 - CSI2_PRINT_REGISTER(iss, csi2->regs1, SHORT_PACKET); 622 - CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_IRQENABLE); 623 - CSI2_PRINT_REGISTER(iss, csi2->regs1, DBG_P); 624 - CSI2_PRINT_REGISTER(iss, csi2->regs1, TIMING); 625 - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL1(0)); 626 - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL2(0)); 627 - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_DAT_OFST(0)); 628 - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_PING_ADDR(0)); 629 - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_PONG_ADDR(0)); 630 - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_IRQENABLE(0)); 631 - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_IRQSTATUS(0)); 632 - CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL3(0)); 633 - 634 - dev_dbg(iss->dev, "--------------------------------------------\n"); 635 - } 636 - 637 - /* ----------------------------------------------------------------------------- 638 - * Interrupt handling 639 - */ 640 - 641 - /* 642 - * csi2_isr_buffer - Does buffer handling at end-of-frame 643 - * when writing to memory. 644 - */ 645 - static void csi2_isr_buffer(struct iss_csi2_device *csi2) 646 - { 647 - struct iss_buffer *buffer; 648 - 649 - csi2_ctx_enable(csi2, 0, 0); 650 - 651 - buffer = omap4iss_video_buffer_next(&csi2->video_out); 652 - 653 - /* 654 - * Let video queue operation restart engine if there is an underrun 655 - * condition. 656 - */ 657 - if (!buffer) 658 - return; 659 - 660 - csi2_set_outaddr(csi2, buffer->iss_addr); 661 - csi2_ctx_enable(csi2, 0, 1); 662 - } 663 - 664 - static void csi2_isr_ctx(struct iss_csi2_device *csi2, 665 - struct iss_csi2_ctx_cfg *ctx) 666 - { 667 - unsigned int n = ctx->ctxnum; 668 - u32 status; 669 - 670 - status = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n)); 671 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n), status); 672 - 673 - if (omap4iss_module_sync_is_stopping(&csi2->wait, &csi2->stopping)) 674 - return; 675 - 676 - /* Propagate frame number */ 677 - if (status & CSI2_CTX_IRQ_FS) { 678 - struct iss_pipeline *pipe = 679 - to_iss_pipeline(&csi2->subdev.entity); 680 - u16 frame; 681 - u16 delta; 682 - 683 - frame = iss_reg_read(csi2->iss, csi2->regs1, 684 - CSI2_CTX_CTRL2(ctx->ctxnum)) 685 - >> CSI2_CTX_CTRL2_FRAME_SHIFT; 686 - 687 - if (frame == 0) { 688 - /* A zero value means that the counter isn't implemented 689 - * by the source. Increment the frame number in software 690 - * in that case. 691 - */ 692 - atomic_inc(&pipe->frame_number); 693 - } else { 694 - /* Extend the 16 bit frame number to 32 bits by 695 - * computing the delta between two consecutive CSI2 696 - * frame numbers and adding it to the software frame 697 - * number. The hardware counter starts at 1 and wraps 698 - * from 0xffff to 1 without going through 0, so subtract 699 - * 1 when the counter wraps. 700 - */ 701 - delta = frame - ctx->frame; 702 - if (frame < ctx->frame) 703 - delta--; 704 - ctx->frame = frame; 705 - 706 - atomic_add(delta, &pipe->frame_number); 707 - } 708 - } 709 - 710 - if (!(status & CSI2_CTX_IRQ_FE)) 711 - return; 712 - 713 - /* Skip interrupts until we reach the frame skip count. The CSI2 will be 714 - * automatically disabled, as the frame skip count has been programmed 715 - * in the CSI2_CTx_CTRL1::COUNT field, so re-enable it. 716 - * 717 - * It would have been nice to rely on the FRAME_NUMBER interrupt instead 718 - * but it turned out that the interrupt is only generated when the CSI2 719 - * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased 720 - * correctly and reaches 0 when data is forwarded to the video port only 721 - * but no interrupt arrives). Maybe a CSI2 hardware bug. 722 - */ 723 - if (csi2->frame_skip) { 724 - csi2->frame_skip--; 725 - if (csi2->frame_skip == 0) { 726 - ctx->format_id = csi2_ctx_map_format(csi2); 727 - csi2_ctx_config(csi2, ctx); 728 - csi2_ctx_enable(csi2, n, 1); 729 - } 730 - return; 731 - } 732 - 733 - if (csi2->output & CSI2_OUTPUT_MEMORY) 734 - csi2_isr_buffer(csi2); 735 - } 736 - 737 - /* 738 - * omap4iss_csi2_isr - CSI2 interrupt handling. 739 - */ 740 - void omap4iss_csi2_isr(struct iss_csi2_device *csi2) 741 - { 742 - struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); 743 - u32 csi2_irqstatus, cpxio1_irqstatus; 744 - struct iss_device *iss = csi2->iss; 745 - 746 - if (!csi2->available) 747 - return; 748 - 749 - csi2_irqstatus = iss_reg_read(csi2->iss, csi2->regs1, CSI2_IRQSTATUS); 750 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQSTATUS, csi2_irqstatus); 751 - 752 - /* Failure Cases */ 753 - if (csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR) { 754 - cpxio1_irqstatus = iss_reg_read(csi2->iss, csi2->regs1, 755 - CSI2_COMPLEXIO_IRQSTATUS); 756 - iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQSTATUS, 757 - cpxio1_irqstatus); 758 - dev_dbg(iss->dev, "CSI2: ComplexIO Error IRQ %x\n", 759 - cpxio1_irqstatus); 760 - pipe->error = true; 761 - } 762 - 763 - if (csi2_irqstatus & (CSI2_IRQ_OCP_ERR | 764 - CSI2_IRQ_SHORT_PACKET | 765 - CSI2_IRQ_ECC_NO_CORRECTION | 766 - CSI2_IRQ_COMPLEXIO_ERR | 767 - CSI2_IRQ_FIFO_OVF)) { 768 - dev_dbg(iss->dev, 769 - "CSI2 Err: OCP:%d SHORT:%d ECC:%d CPXIO:%d OVF:%d\n", 770 - csi2_irqstatus & CSI2_IRQ_OCP_ERR ? 1 : 0, 771 - csi2_irqstatus & CSI2_IRQ_SHORT_PACKET ? 1 : 0, 772 - csi2_irqstatus & CSI2_IRQ_ECC_NO_CORRECTION ? 1 : 0, 773 - csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR ? 1 : 0, 774 - csi2_irqstatus & CSI2_IRQ_FIFO_OVF ? 1 : 0); 775 - pipe->error = true; 776 - } 777 - 778 - /* Successful cases */ 779 - if (csi2_irqstatus & CSI2_IRQ_CONTEXT0) 780 - csi2_isr_ctx(csi2, &csi2->contexts[0]); 781 - 782 - if (csi2_irqstatus & CSI2_IRQ_ECC_CORRECTION) 783 - dev_dbg(iss->dev, "CSI2: ECC correction done\n"); 784 - } 785 - 786 - /* ----------------------------------------------------------------------------- 787 - * ISS video operations 788 - */ 789 - 790 - /* 791 - * csi2_queue - Queues the first buffer when using memory output 792 - * @video: The video node 793 - * @buffer: buffer to queue 794 - */ 795 - static int csi2_queue(struct iss_video *video, struct iss_buffer *buffer) 796 - { 797 - struct iss_csi2_device *csi2 = container_of(video, 798 - struct iss_csi2_device, video_out); 799 - 800 - csi2_set_outaddr(csi2, buffer->iss_addr); 801 - 802 - /* 803 - * If streaming was enabled before there was a buffer queued 804 - * or underrun happened in the ISR, the hardware was not enabled 805 - * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set. 806 - * Enable it now. 807 - */ 808 - if (csi2->video_out.dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { 809 - /* Enable / disable context 0 and IRQs */ 810 - csi2_if_enable(csi2, 1); 811 - csi2_ctx_enable(csi2, 0, 1); 812 - iss_video_dmaqueue_flags_clr(&csi2->video_out); 813 - } 814 - 815 - return 0; 816 - } 817 - 818 - static const struct iss_video_operations csi2_issvideo_ops = { 819 - .queue = csi2_queue, 820 - }; 821 - 822 - /* ----------------------------------------------------------------------------- 823 - * V4L2 subdev operations 824 - */ 825 - 826 - static struct v4l2_mbus_framefmt * 827 - __csi2_get_format(struct iss_csi2_device *csi2, 828 - struct v4l2_subdev_state *sd_state, 829 - unsigned int pad, 830 - enum v4l2_subdev_format_whence which) 831 - { 832 - if (which == V4L2_SUBDEV_FORMAT_TRY) 833 - return v4l2_subdev_state_get_format(sd_state, pad); 834 - 835 - return &csi2->formats[pad]; 836 - } 837 - 838 - static void 839 - csi2_try_format(struct iss_csi2_device *csi2, 840 - struct v4l2_subdev_state *sd_state, 841 - unsigned int pad, 842 - struct v4l2_mbus_framefmt *fmt, 843 - enum v4l2_subdev_format_whence which) 844 - { 845 - u32 pixelcode; 846 - struct v4l2_mbus_framefmt *format; 847 - const struct iss_format_info *info; 848 - unsigned int i; 849 - 850 - switch (pad) { 851 - case CSI2_PAD_SINK: 852 - /* Clamp the width and height to valid range (1-8191). */ 853 - for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) { 854 - if (fmt->code == csi2_input_fmts[i]) 855 - break; 856 - } 857 - 858 - /* If not found, use SGRBG10 as default */ 859 - if (i >= ARRAY_SIZE(csi2_input_fmts)) 860 - fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; 861 - 862 - fmt->width = clamp_t(u32, fmt->width, 1, 8191); 863 - fmt->height = clamp_t(u32, fmt->height, 1, 8191); 864 - break; 865 - 866 - case CSI2_PAD_SOURCE: 867 - /* Source format same as sink format, except for DPCM 868 - * compression. 869 - */ 870 - pixelcode = fmt->code; 871 - format = __csi2_get_format(csi2, sd_state, CSI2_PAD_SINK, 872 - which); 873 - memcpy(fmt, format, sizeof(*fmt)); 874 - 875 - /* 876 - * Only Allow DPCM decompression, and check that the 877 - * pattern is preserved 878 - */ 879 - info = omap4iss_video_format_info(fmt->code); 880 - if (info->uncompressed == pixelcode) 881 - fmt->code = pixelcode; 882 - break; 883 - } 884 - 885 - /* RGB, non-interlaced */ 886 - fmt->colorspace = V4L2_COLORSPACE_SRGB; 887 - fmt->field = V4L2_FIELD_NONE; 888 - } 889 - 890 - /* 891 - * csi2_enum_mbus_code - Handle pixel format enumeration 892 - * @sd : pointer to v4l2 subdev structure 893 - * @sd_state: V4L2 subdev state 894 - * @code : pointer to v4l2_subdev_mbus_code_enum structure 895 - * return -EINVAL or zero on success 896 - */ 897 - static int csi2_enum_mbus_code(struct v4l2_subdev *sd, 898 - struct v4l2_subdev_state *sd_state, 899 - struct v4l2_subdev_mbus_code_enum *code) 900 - { 901 - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); 902 - struct v4l2_mbus_framefmt *format; 903 - const struct iss_format_info *info; 904 - 905 - if (code->pad == CSI2_PAD_SINK) { 906 - if (code->index >= ARRAY_SIZE(csi2_input_fmts)) 907 - return -EINVAL; 908 - 909 - code->code = csi2_input_fmts[code->index]; 910 - } else { 911 - format = __csi2_get_format(csi2, sd_state, CSI2_PAD_SINK, 912 - code->which); 913 - switch (code->index) { 914 - case 0: 915 - /* Passthrough sink pad code */ 916 - code->code = format->code; 917 - break; 918 - case 1: 919 - /* Uncompressed code */ 920 - info = omap4iss_video_format_info(format->code); 921 - if (info->uncompressed == format->code) 922 - return -EINVAL; 923 - 924 - code->code = info->uncompressed; 925 - break; 926 - default: 927 - return -EINVAL; 928 - } 929 - } 930 - 931 - return 0; 932 - } 933 - 934 - static int csi2_enum_frame_size(struct v4l2_subdev *sd, 935 - struct v4l2_subdev_state *sd_state, 936 - struct v4l2_subdev_frame_size_enum *fse) 937 - { 938 - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); 939 - struct v4l2_mbus_framefmt format; 940 - 941 - if (fse->index != 0) 942 - return -EINVAL; 943 - 944 - format.code = fse->code; 945 - format.width = 1; 946 - format.height = 1; 947 - csi2_try_format(csi2, sd_state, fse->pad, &format, fse->which); 948 - fse->min_width = format.width; 949 - fse->min_height = format.height; 950 - 951 - if (format.code != fse->code) 952 - return -EINVAL; 953 - 954 - format.code = fse->code; 955 - format.width = -1; 956 - format.height = -1; 957 - csi2_try_format(csi2, sd_state, fse->pad, &format, fse->which); 958 - fse->max_width = format.width; 959 - fse->max_height = format.height; 960 - 961 - return 0; 962 - } 963 - 964 - /* 965 - * csi2_get_format - Handle get format by pads subdev method 966 - * @sd : pointer to v4l2 subdev structure 967 - * @sd_state: V4L2 subdev state 968 - * @fmt: pointer to v4l2 subdev format structure 969 - * return -EINVAL or zero on success 970 - */ 971 - static int csi2_get_format(struct v4l2_subdev *sd, 972 - struct v4l2_subdev_state *sd_state, 973 - struct v4l2_subdev_format *fmt) 974 - { 975 - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); 976 - struct v4l2_mbus_framefmt *format; 977 - 978 - format = __csi2_get_format(csi2, sd_state, fmt->pad, fmt->which); 979 - if (!format) 980 - return -EINVAL; 981 - 982 - fmt->format = *format; 983 - return 0; 984 - } 985 - 986 - /* 987 - * csi2_set_format - Handle set format by pads subdev method 988 - * @sd : pointer to v4l2 subdev structure 989 - * @sd_state: V4L2 subdev state 990 - * @fmt: pointer to v4l2 subdev format structure 991 - * return -EINVAL or zero on success 992 - */ 993 - static int csi2_set_format(struct v4l2_subdev *sd, 994 - struct v4l2_subdev_state *sd_state, 995 - struct v4l2_subdev_format *fmt) 996 - { 997 - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); 998 - struct v4l2_mbus_framefmt *format; 999 - 1000 - format = __csi2_get_format(csi2, sd_state, fmt->pad, fmt->which); 1001 - if (!format) 1002 - return -EINVAL; 1003 - 1004 - csi2_try_format(csi2, sd_state, fmt->pad, &fmt->format, fmt->which); 1005 - *format = fmt->format; 1006 - 1007 - /* Propagate the format from sink to source */ 1008 - if (fmt->pad == CSI2_PAD_SINK) { 1009 - format = __csi2_get_format(csi2, sd_state, CSI2_PAD_SOURCE, 1010 - fmt->which); 1011 - *format = fmt->format; 1012 - csi2_try_format(csi2, sd_state, CSI2_PAD_SOURCE, format, 1013 - fmt->which); 1014 - } 1015 - 1016 - return 0; 1017 - } 1018 - 1019 - static int csi2_link_validate(struct v4l2_subdev *sd, struct media_link *link, 1020 - struct v4l2_subdev_format *source_fmt, 1021 - struct v4l2_subdev_format *sink_fmt) 1022 - { 1023 - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); 1024 - struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); 1025 - int rval; 1026 - 1027 - pipe->external = media_entity_to_v4l2_subdev(link->source->entity); 1028 - rval = omap4iss_get_external_info(pipe, link); 1029 - if (rval < 0) 1030 - return rval; 1031 - 1032 - return v4l2_subdev_link_validate_default(sd, link, source_fmt, 1033 - sink_fmt); 1034 - } 1035 - 1036 - /* 1037 - * csi2_init_formats - Initialize formats on all pads 1038 - * @sd: ISS CSI2 V4L2 subdevice 1039 - * @fh: V4L2 subdev file handle 1040 - * 1041 - * Initialize all pad formats with default values. If fh is not NULL, try 1042 - * formats are initialized on the file handle. Otherwise active formats are 1043 - * initialized on the device. 1044 - */ 1045 - static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 1046 - { 1047 - struct v4l2_subdev_format format; 1048 - 1049 - memset(&format, 0, sizeof(format)); 1050 - format.pad = CSI2_PAD_SINK; 1051 - format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; 1052 - format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10; 1053 - format.format.width = 4096; 1054 - format.format.height = 4096; 1055 - csi2_set_format(sd, fh ? fh->state : NULL, &format); 1056 - 1057 - return 0; 1058 - } 1059 - 1060 - /* 1061 - * csi2_set_stream - Enable/Disable streaming on the CSI2 module 1062 - * @sd: ISS CSI2 V4L2 subdevice 1063 - * @enable: ISS pipeline stream state 1064 - * 1065 - * Return 0 on success or a negative error code otherwise. 1066 - */ 1067 - static int csi2_set_stream(struct v4l2_subdev *sd, int enable) 1068 - { 1069 - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); 1070 - struct iss_device *iss = csi2->iss; 1071 - struct iss_video *video_out = &csi2->video_out; 1072 - int ret = 0; 1073 - 1074 - if (csi2->state == ISS_PIPELINE_STREAM_STOPPED) { 1075 - if (enable == ISS_PIPELINE_STREAM_STOPPED) 1076 - return 0; 1077 - 1078 - omap4iss_subclk_enable(iss, csi2->subclk); 1079 - } 1080 - 1081 - switch (enable) { 1082 - case ISS_PIPELINE_STREAM_CONTINUOUS: { 1083 - ret = omap4iss_csiphy_config(iss, sd); 1084 - if (ret < 0) 1085 - return ret; 1086 - 1087 - if (omap4iss_csiphy_acquire(csi2->phy) < 0) 1088 - return -ENODEV; 1089 - csi2_configure(csi2); 1090 - csi2_print_status(csi2); 1091 - 1092 - /* 1093 - * When outputting to memory with no buffer available, let the 1094 - * buffer queue handler start the hardware. A DMA queue flag 1095 - * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is 1096 - * a buffer available. 1097 - */ 1098 - if (csi2->output & CSI2_OUTPUT_MEMORY && 1099 - !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED)) 1100 - break; 1101 - /* Enable context 0 and IRQs */ 1102 - atomic_set(&csi2->stopping, 0); 1103 - csi2_ctx_enable(csi2, 0, 1); 1104 - csi2_if_enable(csi2, 1); 1105 - iss_video_dmaqueue_flags_clr(video_out); 1106 - break; 1107 - } 1108 - case ISS_PIPELINE_STREAM_STOPPED: 1109 - if (csi2->state == ISS_PIPELINE_STREAM_STOPPED) 1110 - return 0; 1111 - if (omap4iss_module_sync_idle(&sd->entity, &csi2->wait, 1112 - &csi2->stopping)) 1113 - ret = -ETIMEDOUT; 1114 - csi2_ctx_enable(csi2, 0, 0); 1115 - csi2_if_enable(csi2, 0); 1116 - csi2_irq_ctx_set(csi2, 0); 1117 - omap4iss_csiphy_release(csi2->phy); 1118 - omap4iss_subclk_disable(iss, csi2->subclk); 1119 - iss_video_dmaqueue_flags_clr(video_out); 1120 - break; 1121 - } 1122 - 1123 - csi2->state = enable; 1124 - return ret; 1125 - } 1126 - 1127 - /* subdev video operations */ 1128 - static const struct v4l2_subdev_video_ops csi2_video_ops = { 1129 - .s_stream = csi2_set_stream, 1130 - }; 1131 - 1132 - /* subdev pad operations */ 1133 - static const struct v4l2_subdev_pad_ops csi2_pad_ops = { 1134 - .enum_mbus_code = csi2_enum_mbus_code, 1135 - .enum_frame_size = csi2_enum_frame_size, 1136 - .get_fmt = csi2_get_format, 1137 - .set_fmt = csi2_set_format, 1138 - .link_validate = csi2_link_validate, 1139 - }; 1140 - 1141 - /* subdev operations */ 1142 - static const struct v4l2_subdev_ops csi2_ops = { 1143 - .video = &csi2_video_ops, 1144 - .pad = &csi2_pad_ops, 1145 - }; 1146 - 1147 - /* subdev internal operations */ 1148 - static const struct v4l2_subdev_internal_ops csi2_internal_ops = { 1149 - .open = csi2_init_formats, 1150 - }; 1151 - 1152 - /* ----------------------------------------------------------------------------- 1153 - * Media entity operations 1154 - */ 1155 - 1156 - /* 1157 - * csi2_link_setup - Setup CSI2 connections. 1158 - * @entity : Pointer to media entity structure 1159 - * @local : Pointer to local pad array 1160 - * @remote : Pointer to remote pad array 1161 - * @flags : Link flags 1162 - * return -EINVAL or zero on success 1163 - */ 1164 - static int csi2_link_setup(struct media_entity *entity, 1165 - const struct media_pad *local, 1166 - const struct media_pad *remote, u32 flags) 1167 - { 1168 - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); 1169 - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); 1170 - struct iss_csi2_ctrl_cfg *ctrl = &csi2->ctrl; 1171 - unsigned int index = local->index; 1172 - 1173 - /* FIXME: this is actually a hack! */ 1174 - if (is_media_entity_v4l2_subdev(remote->entity)) 1175 - index |= 2 << 16; 1176 - 1177 - /* 1178 - * The ISS core doesn't support pipelines with multiple video outputs. 1179 - * Revisit this when it will be implemented, and return -EBUSY for now. 1180 - */ 1181 - 1182 - switch (index) { 1183 - case CSI2_PAD_SOURCE: 1184 - if (flags & MEDIA_LNK_FL_ENABLED) { 1185 - if (csi2->output & ~CSI2_OUTPUT_MEMORY) 1186 - return -EBUSY; 1187 - csi2->output |= CSI2_OUTPUT_MEMORY; 1188 - } else { 1189 - csi2->output &= ~CSI2_OUTPUT_MEMORY; 1190 - } 1191 - break; 1192 - 1193 - case CSI2_PAD_SOURCE | 2 << 16: 1194 - if (flags & MEDIA_LNK_FL_ENABLED) { 1195 - if (csi2->output & ~CSI2_OUTPUT_IPIPEIF) 1196 - return -EBUSY; 1197 - csi2->output |= CSI2_OUTPUT_IPIPEIF; 1198 - } else { 1199 - csi2->output &= ~CSI2_OUTPUT_IPIPEIF; 1200 - } 1201 - break; 1202 - 1203 - default: 1204 - /* Link from camera to CSI2 is fixed... */ 1205 - return -EINVAL; 1206 - } 1207 - 1208 - ctrl->vp_only_enable = csi2->output & CSI2_OUTPUT_MEMORY ? false : true; 1209 - ctrl->vp_clk_enable = !!(csi2->output & CSI2_OUTPUT_IPIPEIF); 1210 - 1211 - return 0; 1212 - } 1213 - 1214 - /* media operations */ 1215 - static const struct media_entity_operations csi2_media_ops = { 1216 - .link_setup = csi2_link_setup, 1217 - .link_validate = v4l2_subdev_link_validate, 1218 - }; 1219 - 1220 - void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2) 1221 - { 1222 - v4l2_device_unregister_subdev(&csi2->subdev); 1223 - omap4iss_video_unregister(&csi2->video_out); 1224 - } 1225 - 1226 - int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2, 1227 - struct v4l2_device *vdev) 1228 - { 1229 - int ret; 1230 - 1231 - /* Register the subdev and video nodes. */ 1232 - ret = v4l2_device_register_subdev(vdev, &csi2->subdev); 1233 - if (ret < 0) 1234 - goto error; 1235 - 1236 - ret = omap4iss_video_register(&csi2->video_out, vdev); 1237 - if (ret < 0) 1238 - goto error; 1239 - 1240 - return 0; 1241 - 1242 - error: 1243 - omap4iss_csi2_unregister_entities(csi2); 1244 - return ret; 1245 - } 1246 - 1247 - /* ----------------------------------------------------------------------------- 1248 - * ISS CSI2 initialisation and cleanup 1249 - */ 1250 - 1251 - /* 1252 - * csi2_init_entities - Initialize subdev and media entity. 1253 - * @csi2: Pointer to csi2 structure. 1254 - * return -ENOMEM or zero on success 1255 - */ 1256 - static int csi2_init_entities(struct iss_csi2_device *csi2, const char *subname) 1257 - { 1258 - struct v4l2_subdev *sd = &csi2->subdev; 1259 - struct media_pad *pads = csi2->pads; 1260 - struct media_entity *me = &sd->entity; 1261 - int ret; 1262 - char name[32]; 1263 - 1264 - v4l2_subdev_init(sd, &csi2_ops); 1265 - sd->internal_ops = &csi2_internal_ops; 1266 - snprintf(name, sizeof(name), "CSI2%s", subname); 1267 - snprintf(sd->name, sizeof(sd->name), "OMAP4 ISS %s", name); 1268 - 1269 - sd->grp_id = BIT(16); /* group ID for iss subdevs */ 1270 - v4l2_set_subdevdata(sd, csi2); 1271 - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 1272 - 1273 - pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; 1274 - pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 1275 - 1276 - me->ops = &csi2_media_ops; 1277 - ret = media_entity_pads_init(me, CSI2_PADS_NUM, pads); 1278 - if (ret < 0) 1279 - return ret; 1280 - 1281 - csi2_init_formats(sd, NULL); 1282 - 1283 - /* Video device node */ 1284 - csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1285 - csi2->video_out.ops = &csi2_issvideo_ops; 1286 - csi2->video_out.bpl_alignment = 32; 1287 - csi2->video_out.bpl_zero_padding = 1; 1288 - csi2->video_out.bpl_max = 0x1ffe0; 1289 - csi2->video_out.iss = csi2->iss; 1290 - csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; 1291 - 1292 - ret = omap4iss_video_init(&csi2->video_out, name); 1293 - if (ret < 0) 1294 - goto error_video; 1295 - 1296 - return 0; 1297 - 1298 - error_video: 1299 - media_entity_cleanup(&csi2->subdev.entity); 1300 - return ret; 1301 - } 1302 - 1303 - /* 1304 - * omap4iss_csi2_init - Routine for module driver init 1305 - */ 1306 - int omap4iss_csi2_init(struct iss_device *iss) 1307 - { 1308 - struct iss_csi2_device *csi2a = &iss->csi2a; 1309 - struct iss_csi2_device *csi2b = &iss->csi2b; 1310 - int ret; 1311 - 1312 - csi2a->iss = iss; 1313 - csi2a->available = 1; 1314 - csi2a->regs1 = OMAP4_ISS_MEM_CSI2_A_REGS1; 1315 - csi2a->phy = &iss->csiphy1; 1316 - csi2a->subclk = OMAP4_ISS_SUBCLK_CSI2_A; 1317 - csi2a->state = ISS_PIPELINE_STREAM_STOPPED; 1318 - init_waitqueue_head(&csi2a->wait); 1319 - 1320 - ret = csi2_init_entities(csi2a, "a"); 1321 - if (ret < 0) 1322 - return ret; 1323 - 1324 - csi2b->iss = iss; 1325 - csi2b->available = 1; 1326 - csi2b->regs1 = OMAP4_ISS_MEM_CSI2_B_REGS1; 1327 - csi2b->phy = &iss->csiphy2; 1328 - csi2b->subclk = OMAP4_ISS_SUBCLK_CSI2_B; 1329 - csi2b->state = ISS_PIPELINE_STREAM_STOPPED; 1330 - init_waitqueue_head(&csi2b->wait); 1331 - 1332 - ret = csi2_init_entities(csi2b, "b"); 1333 - if (ret < 0) 1334 - return ret; 1335 - 1336 - return 0; 1337 - } 1338 - 1339 - /* 1340 - * omap4iss_csi2_create_links() - CSI2 pads links creation 1341 - * @iss: Pointer to ISS device 1342 - * 1343 - * return negative error code or zero on success 1344 - */ 1345 - int omap4iss_csi2_create_links(struct iss_device *iss) 1346 - { 1347 - struct iss_csi2_device *csi2a = &iss->csi2a; 1348 - struct iss_csi2_device *csi2b = &iss->csi2b; 1349 - int ret; 1350 - 1351 - /* Connect the CSI2a subdev to the video node. */ 1352 - ret = media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE, 1353 - &csi2a->video_out.video.entity, 0, 0); 1354 - if (ret < 0) 1355 - return ret; 1356 - 1357 - /* Connect the CSI2b subdev to the video node. */ 1358 - ret = media_create_pad_link(&csi2b->subdev.entity, CSI2_PAD_SOURCE, 1359 - &csi2b->video_out.video.entity, 0, 0); 1360 - if (ret < 0) 1361 - return ret; 1362 - 1363 - return 0; 1364 - } 1365 - 1366 - /* 1367 - * omap4iss_csi2_cleanup - Routine for module driver cleanup 1368 - */ 1369 - void omap4iss_csi2_cleanup(struct iss_device *iss) 1370 - { 1371 - struct iss_csi2_device *csi2a = &iss->csi2a; 1372 - struct iss_csi2_device *csi2b = &iss->csi2b; 1373 - 1374 - omap4iss_video_cleanup(&csi2a->video_out); 1375 - media_entity_cleanup(&csi2a->subdev.entity); 1376 - 1377 - omap4iss_video_cleanup(&csi2b->video_out); 1378 - media_entity_cleanup(&csi2b->subdev.entity); 1379 - }
-155
drivers/staging/media/omap4iss/iss_csi2.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ */ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - CSI2 module 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #ifndef OMAP4_ISS_CSI2_H 11 - #define OMAP4_ISS_CSI2_H 12 - 13 - #include <linux/types.h> 14 - #include <linux/videodev2.h> 15 - 16 - #include "iss_video.h" 17 - 18 - struct iss_csiphy; 19 - 20 - /* This is not an exhaustive list */ 21 - enum iss_csi2_pix_formats { 22 - CSI2_PIX_FMT_OTHERS = 0, 23 - CSI2_PIX_FMT_YUV422_8BIT = 0x1e, 24 - CSI2_PIX_FMT_YUV422_8BIT_VP = 0x9e, 25 - CSI2_PIX_FMT_YUV422_8BIT_VP16 = 0xde, 26 - CSI2_PIX_FMT_RAW10_EXP16 = 0xab, 27 - CSI2_PIX_FMT_RAW10_EXP16_VP = 0x12f, 28 - CSI2_PIX_FMT_RAW8 = 0x2a, 29 - CSI2_PIX_FMT_RAW8_DPCM10_EXP16 = 0x2aa, 30 - CSI2_PIX_FMT_RAW8_DPCM10_VP = 0x32a, 31 - CSI2_PIX_FMT_RAW8_VP = 0x12a, 32 - CSI2_USERDEF_8BIT_DATA1_DPCM10_VP = 0x340, 33 - CSI2_USERDEF_8BIT_DATA1_DPCM10 = 0x2c0, 34 - CSI2_USERDEF_8BIT_DATA1 = 0x40, 35 - }; 36 - 37 - enum iss_csi2_irqevents { 38 - OCP_ERR_IRQ = 0x4000, 39 - SHORT_PACKET_IRQ = 0x2000, 40 - ECC_CORRECTION_IRQ = 0x1000, 41 - ECC_NO_CORRECTION_IRQ = 0x800, 42 - COMPLEXIO2_ERR_IRQ = 0x400, 43 - COMPLEXIO1_ERR_IRQ = 0x200, 44 - FIFO_OVF_IRQ = 0x100, 45 - CONTEXT7 = 0x80, 46 - CONTEXT6 = 0x40, 47 - CONTEXT5 = 0x20, 48 - CONTEXT4 = 0x10, 49 - CONTEXT3 = 0x8, 50 - CONTEXT2 = 0x4, 51 - CONTEXT1 = 0x2, 52 - CONTEXT0 = 0x1, 53 - }; 54 - 55 - enum iss_csi2_ctx_irqevents { 56 - CTX_ECC_CORRECTION = 0x100, 57 - CTX_LINE_NUMBER = 0x80, 58 - CTX_FRAME_NUMBER = 0x40, 59 - CTX_CS = 0x20, 60 - CTX_LE = 0x8, 61 - CTX_LS = 0x4, 62 - CTX_FE = 0x2, 63 - CTX_FS = 0x1, 64 - }; 65 - 66 - enum iss_csi2_frame_mode { 67 - ISS_CSI2_FRAME_IMMEDIATE, 68 - ISS_CSI2_FRAME_AFTERFEC, 69 - }; 70 - 71 - #define ISS_CSI2_MAX_CTX_NUM 7 72 - 73 - struct iss_csi2_ctx_cfg { 74 - u8 ctxnum; /* context number 0 - 7 */ 75 - u8 dpcm_decompress; 76 - 77 - /* Fields in CSI2_CTx_CTRL2 - locked by CSI2_CTx_CTRL1.CTX_EN */ 78 - u8 virtual_id; 79 - u16 format_id; /* as in CSI2_CTx_CTRL2[9:0] */ 80 - u8 dpcm_predictor; /* 1: simple, 0: advanced */ 81 - u16 frame; 82 - 83 - /* Fields in CSI2_CTx_CTRL1/3 - Shadowed */ 84 - u16 alpha; 85 - u16 data_offset; 86 - u32 ping_addr; 87 - u32 pong_addr; 88 - u8 eof_enabled; 89 - u8 eol_enabled; 90 - u8 checksum_enabled; 91 - u8 enabled; 92 - }; 93 - 94 - struct iss_csi2_timing_cfg { 95 - u8 ionum; /* IO1 or IO2 as in CSI2_TIMING */ 96 - unsigned force_rx_mode:1; 97 - unsigned stop_state_16x:1; 98 - unsigned stop_state_4x:1; 99 - u16 stop_state_counter; 100 - }; 101 - 102 - struct iss_csi2_ctrl_cfg { 103 - bool vp_clk_enable; 104 - bool vp_only_enable; 105 - u8 vp_out_ctrl; 106 - enum iss_csi2_frame_mode frame_mode; 107 - bool ecc_enable; 108 - bool if_enable; 109 - }; 110 - 111 - #define CSI2_PAD_SINK 0 112 - #define CSI2_PAD_SOURCE 1 113 - #define CSI2_PADS_NUM 2 114 - 115 - #define CSI2_OUTPUT_IPIPEIF BIT(0) 116 - #define CSI2_OUTPUT_MEMORY BIT(1) 117 - 118 - struct iss_csi2_device { 119 - struct v4l2_subdev subdev; 120 - struct media_pad pads[CSI2_PADS_NUM]; 121 - struct v4l2_mbus_framefmt formats[CSI2_PADS_NUM]; 122 - 123 - struct iss_video video_out; 124 - struct iss_device *iss; 125 - 126 - u8 available; /* Is the IP present on the silicon? */ 127 - 128 - /* memory resources, as defined in enum iss_mem_resources */ 129 - unsigned int regs1; 130 - unsigned int regs2; 131 - /* ISP subclock, as defined in enum iss_isp_subclk_resource */ 132 - unsigned int subclk; 133 - 134 - u32 output; /* output to IPIPEIF, memory or both? */ 135 - bool dpcm_decompress; 136 - unsigned int frame_skip; 137 - 138 - struct iss_csiphy *phy; 139 - struct iss_csi2_ctx_cfg contexts[ISS_CSI2_MAX_CTX_NUM + 1]; 140 - struct iss_csi2_timing_cfg timing[2]; 141 - struct iss_csi2_ctrl_cfg ctrl; 142 - enum iss_pipeline_stream_state state; 143 - wait_queue_head_t wait; 144 - atomic_t stopping; 145 - }; 146 - 147 - void omap4iss_csi2_isr(struct iss_csi2_device *csi2); 148 - int omap4iss_csi2_reset(struct iss_csi2_device *csi2); 149 - int omap4iss_csi2_init(struct iss_device *iss); 150 - int omap4iss_csi2_create_links(struct iss_device *iss); 151 - void omap4iss_csi2_cleanup(struct iss_device *iss); 152 - void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2); 153 - int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2, 154 - struct v4l2_device *vdev); 155 - #endif /* OMAP4_ISS_CSI2_H */
-277
drivers/staging/media/omap4iss/iss_csiphy.c
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - CSI PHY module 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #include <linux/delay.h> 11 - #include <linux/device.h> 12 - #include <linux/regmap.h> 13 - 14 - #include "../../../../arch/arm/mach-omap2/control.h" 15 - 16 - #include "iss.h" 17 - #include "iss_regs.h" 18 - #include "iss_csiphy.h" 19 - 20 - /* 21 - * csiphy_lanes_config - Configuration of CSIPHY lanes. 22 - * 23 - * Updates HW configuration. 24 - * Called with phy->mutex taken. 25 - */ 26 - static void csiphy_lanes_config(struct iss_csiphy *phy) 27 - { 28 - unsigned int i; 29 - u32 reg; 30 - 31 - reg = iss_reg_read(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG); 32 - 33 - for (i = 0; i < phy->max_data_lanes; i++) { 34 - reg &= ~(CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) | 35 - CSI2_COMPLEXIO_CFG_DATA_POSITION_MASK(i + 1)); 36 - reg |= (phy->lanes.data[i].pol ? 37 - CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) : 0); 38 - reg |= (phy->lanes.data[i].pos << 39 - CSI2_COMPLEXIO_CFG_DATA_POSITION_SHIFT(i + 1)); 40 - } 41 - 42 - reg &= ~(CSI2_COMPLEXIO_CFG_CLOCK_POL | 43 - CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK); 44 - reg |= phy->lanes.clk.pol ? CSI2_COMPLEXIO_CFG_CLOCK_POL : 0; 45 - reg |= phy->lanes.clk.pos << CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT; 46 - 47 - iss_reg_write(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG, reg); 48 - } 49 - 50 - /* 51 - * csiphy_set_power 52 - * @power: Power state to be set. 53 - * 54 - * Returns 0 if successful, or -EBUSY if the retry count is exceeded. 55 - */ 56 - static int csiphy_set_power(struct iss_csiphy *phy, u32 power) 57 - { 58 - u32 reg; 59 - u8 retry_count; 60 - 61 - iss_reg_update(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG, 62 - CSI2_COMPLEXIO_CFG_PWD_CMD_MASK, 63 - power | CSI2_COMPLEXIO_CFG_PWR_AUTO); 64 - 65 - retry_count = 0; 66 - do { 67 - udelay(1); 68 - reg = iss_reg_read(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG) 69 - & CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK; 70 - 71 - if (reg != power >> 2) 72 - retry_count++; 73 - 74 - } while ((reg != power >> 2) && (retry_count < 250)); 75 - 76 - if (retry_count == 250) { 77 - dev_err(phy->iss->dev, "CSI2 CIO set power failed!\n"); 78 - return -EBUSY; 79 - } 80 - 81 - return 0; 82 - } 83 - 84 - /* 85 - * csiphy_dphy_config - Configure CSI2 D-PHY parameters. 86 - * 87 - * Called with phy->mutex taken. 88 - */ 89 - static void csiphy_dphy_config(struct iss_csiphy *phy) 90 - { 91 - u32 reg; 92 - 93 - /* Set up REGISTER0 */ 94 - reg = phy->dphy.ths_term << REGISTER0_THS_TERM_SHIFT; 95 - reg |= phy->dphy.ths_settle << REGISTER0_THS_SETTLE_SHIFT; 96 - 97 - iss_reg_write(phy->iss, phy->phy_regs, REGISTER0, reg); 98 - 99 - /* Set up REGISTER1 */ 100 - reg = phy->dphy.tclk_term << REGISTER1_TCLK_TERM_SHIFT; 101 - reg |= phy->dphy.tclk_miss << REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT; 102 - reg |= phy->dphy.tclk_settle << REGISTER1_TCLK_SETTLE_SHIFT; 103 - reg |= 0xb8 << REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT; 104 - 105 - iss_reg_write(phy->iss, phy->phy_regs, REGISTER1, reg); 106 - } 107 - 108 - /* 109 - * TCLK values are OK at their reset values 110 - */ 111 - #define TCLK_TERM 0 112 - #define TCLK_MISS 1 113 - #define TCLK_SETTLE 14 114 - 115 - int omap4iss_csiphy_config(struct iss_device *iss, 116 - struct v4l2_subdev *csi2_subdev) 117 - { 118 - struct iss_csi2_device *csi2 = v4l2_get_subdevdata(csi2_subdev); 119 - struct iss_pipeline *pipe = to_iss_pipeline(&csi2_subdev->entity); 120 - struct iss_v4l2_subdevs_group *subdevs = pipe->external->host_priv; 121 - struct iss_csiphy_dphy_cfg csi2phy; 122 - int csi2_ddrclk_khz; 123 - struct iss_csiphy_lanes_cfg *lanes; 124 - unsigned int used_lanes = 0; 125 - u32 cam_rx_ctrl; 126 - unsigned int i; 127 - 128 - lanes = &subdevs->bus.csi2.lanecfg; 129 - 130 - /* 131 - * SCM.CONTROL_CAMERA_RX 132 - * - bit [31] : CSIPHY2 lane 2 enable (4460+ only) 133 - * - bit [30:29] : CSIPHY2 per-lane enable (1 to 0) 134 - * - bit [28:24] : CSIPHY1 per-lane enable (4 to 0) 135 - * - bit [21] : CSIPHY2 CTRLCLK enable 136 - * - bit [20:19] : CSIPHY2 config: 00 d-phy, 01/10 ccp2 137 - * - bit [18] : CSIPHY1 CTRLCLK enable 138 - * - bit [17:16] : CSIPHY1 config: 00 d-phy, 01/10 ccp2 139 - */ 140 - /* 141 - * TODO: When implementing DT support specify the CONTROL_CAMERA_RX 142 - * register offset in the syscon property instead of hardcoding it. 143 - */ 144 - regmap_read(iss->syscon, 0x68, &cam_rx_ctrl); 145 - 146 - if (subdevs->interface == ISS_INTERFACE_CSI2A_PHY1) { 147 - cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI21_LANEENABLE_MASK | 148 - OMAP4_CAMERARX_CSI21_CAMMODE_MASK); 149 - /* NOTE: Leave CSIPHY1 config to 0x0: D-PHY mode */ 150 - /* Enable all lanes for now */ 151 - cam_rx_ctrl |= 152 - 0x1f << OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT; 153 - /* Enable CTRLCLK */ 154 - cam_rx_ctrl |= OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK; 155 - } 156 - 157 - if (subdevs->interface == ISS_INTERFACE_CSI2B_PHY2) { 158 - cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI22_LANEENABLE_MASK | 159 - OMAP4_CAMERARX_CSI22_CAMMODE_MASK); 160 - /* NOTE: Leave CSIPHY2 config to 0x0: D-PHY mode */ 161 - /* Enable all lanes for now */ 162 - cam_rx_ctrl |= 163 - 0x3 << OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT; 164 - /* Enable CTRLCLK */ 165 - cam_rx_ctrl |= OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK; 166 - } 167 - 168 - regmap_write(iss->syscon, 0x68, cam_rx_ctrl); 169 - 170 - /* Reset used lane count */ 171 - csi2->phy->used_data_lanes = 0; 172 - 173 - /* Clock and data lanes verification */ 174 - for (i = 0; i < csi2->phy->max_data_lanes; i++) { 175 - if (lanes->data[i].pos == 0) 176 - continue; 177 - 178 - if (lanes->data[i].pol > 1 || 179 - lanes->data[i].pos > (csi2->phy->max_data_lanes + 1)) 180 - return -EINVAL; 181 - 182 - if (used_lanes & (1 << lanes->data[i].pos)) 183 - return -EINVAL; 184 - 185 - used_lanes |= 1 << lanes->data[i].pos; 186 - csi2->phy->used_data_lanes++; 187 - } 188 - 189 - if (lanes->clk.pol > 1 || 190 - lanes->clk.pos > (csi2->phy->max_data_lanes + 1)) 191 - return -EINVAL; 192 - 193 - if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos)) 194 - return -EINVAL; 195 - 196 - csi2_ddrclk_khz = pipe->external_rate / 1000 197 - / (2 * csi2->phy->used_data_lanes) 198 - * pipe->external_bpp; 199 - 200 - /* 201 - * THS_TERM: Programmed value = ceil(12.5 ns/DDRClk period) - 1. 202 - * THS_SETTLE: Programmed value = ceil(90 ns/DDRClk period) + 3. 203 - */ 204 - csi2phy.ths_term = DIV_ROUND_UP(25 * csi2_ddrclk_khz, 2000000) - 1; 205 - csi2phy.ths_settle = DIV_ROUND_UP(90 * csi2_ddrclk_khz, 1000000) + 3; 206 - csi2phy.tclk_term = TCLK_TERM; 207 - csi2phy.tclk_miss = TCLK_MISS; 208 - csi2phy.tclk_settle = TCLK_SETTLE; 209 - 210 - mutex_lock(&csi2->phy->mutex); 211 - csi2->phy->dphy = csi2phy; 212 - csi2->phy->lanes = *lanes; 213 - mutex_unlock(&csi2->phy->mutex); 214 - 215 - return 0; 216 - } 217 - 218 - int omap4iss_csiphy_acquire(struct iss_csiphy *phy) 219 - { 220 - int rval; 221 - 222 - mutex_lock(&phy->mutex); 223 - 224 - rval = omap4iss_csi2_reset(phy->csi2); 225 - if (rval) 226 - goto done; 227 - 228 - csiphy_dphy_config(phy); 229 - csiphy_lanes_config(phy); 230 - 231 - rval = csiphy_set_power(phy, CSI2_COMPLEXIO_CFG_PWD_CMD_ON); 232 - if (rval) 233 - goto done; 234 - 235 - phy->phy_in_use = 1; 236 - 237 - done: 238 - mutex_unlock(&phy->mutex); 239 - return rval; 240 - } 241 - 242 - void omap4iss_csiphy_release(struct iss_csiphy *phy) 243 - { 244 - mutex_lock(&phy->mutex); 245 - if (phy->phy_in_use) { 246 - csiphy_set_power(phy, CSI2_COMPLEXIO_CFG_PWD_CMD_OFF); 247 - phy->phy_in_use = 0; 248 - } 249 - mutex_unlock(&phy->mutex); 250 - } 251 - 252 - /* 253 - * omap4iss_csiphy_init - Initialize the CSI PHY frontends 254 - */ 255 - int omap4iss_csiphy_init(struct iss_device *iss) 256 - { 257 - struct iss_csiphy *phy1 = &iss->csiphy1; 258 - struct iss_csiphy *phy2 = &iss->csiphy2; 259 - 260 - phy1->iss = iss; 261 - phy1->csi2 = &iss->csi2a; 262 - phy1->max_data_lanes = ISS_CSIPHY1_NUM_DATA_LANES; 263 - phy1->used_data_lanes = 0; 264 - phy1->cfg_regs = OMAP4_ISS_MEM_CSI2_A_REGS1; 265 - phy1->phy_regs = OMAP4_ISS_MEM_CAMERARX_CORE1; 266 - mutex_init(&phy1->mutex); 267 - 268 - phy2->iss = iss; 269 - phy2->csi2 = &iss->csi2b; 270 - phy2->max_data_lanes = ISS_CSIPHY2_NUM_DATA_LANES; 271 - phy2->used_data_lanes = 0; 272 - phy2->cfg_regs = OMAP4_ISS_MEM_CSI2_B_REGS1; 273 - phy2->phy_regs = OMAP4_ISS_MEM_CAMERARX_CORE2; 274 - mutex_init(&phy2->mutex); 275 - 276 - return 0; 277 - }
-47
drivers/staging/media/omap4iss/iss_csiphy.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ */ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - CSI PHY module 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #ifndef OMAP4_ISS_CSI_PHY_H 11 - #define OMAP4_ISS_CSI_PHY_H 12 - 13 - #include <linux/platform_data/media/omap4iss.h> 14 - 15 - struct iss_csi2_device; 16 - 17 - struct iss_csiphy_dphy_cfg { 18 - u8 ths_term; 19 - u8 ths_settle; 20 - u8 tclk_term; 21 - unsigned tclk_miss:1; 22 - u8 tclk_settle; 23 - }; 24 - 25 - struct iss_csiphy { 26 - struct iss_device *iss; 27 - struct mutex mutex; /* serialize csiphy configuration */ 28 - u8 phy_in_use; 29 - struct iss_csi2_device *csi2; 30 - 31 - /* memory resources, as defined in enum iss_mem_resources */ 32 - unsigned int cfg_regs; 33 - unsigned int phy_regs; 34 - 35 - u8 max_data_lanes; /* number of CSI2 Data Lanes supported */ 36 - u8 used_data_lanes; /* number of CSI2 Data Lanes used */ 37 - struct iss_csiphy_lanes_cfg lanes; 38 - struct iss_csiphy_dphy_cfg dphy; 39 - }; 40 - 41 - int omap4iss_csiphy_config(struct iss_device *iss, 42 - struct v4l2_subdev *csi2_subdev); 43 - int omap4iss_csiphy_acquire(struct iss_csiphy *phy); 44 - void omap4iss_csiphy_release(struct iss_csiphy *phy); 45 - int omap4iss_csiphy_init(struct iss_device *iss); 46 - 47 - #endif /* OMAP4_ISS_CSI_PHY_H */
-579
drivers/staging/media/omap4iss/iss_ipipe.c
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #include <linux/module.h> 11 - #include <linux/uaccess.h> 12 - #include <linux/delay.h> 13 - #include <linux/device.h> 14 - #include <linux/dma-mapping.h> 15 - #include <linux/mm.h> 16 - #include <linux/sched.h> 17 - 18 - #include "iss.h" 19 - #include "iss_regs.h" 20 - #include "iss_ipipe.h" 21 - 22 - static struct v4l2_mbus_framefmt * 23 - __ipipe_get_format(struct iss_ipipe_device *ipipe, 24 - struct v4l2_subdev_state *sd_state, 25 - unsigned int pad, 26 - enum v4l2_subdev_format_whence which); 27 - 28 - static const unsigned int ipipe_fmts[] = { 29 - MEDIA_BUS_FMT_SGRBG10_1X10, 30 - MEDIA_BUS_FMT_SRGGB10_1X10, 31 - MEDIA_BUS_FMT_SBGGR10_1X10, 32 - MEDIA_BUS_FMT_SGBRG10_1X10, 33 - }; 34 - 35 - /* 36 - * ipipe_print_status - Print current IPIPE Module register values. 37 - * @ipipe: Pointer to ISS ISP IPIPE device. 38 - * 39 - * Also prints other debug information stored in the IPIPE module. 40 - */ 41 - #define IPIPE_PRINT_REGISTER(iss, name)\ 42 - dev_dbg(iss->dev, "###IPIPE " #name "=0x%08x\n", \ 43 - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_##name)) 44 - 45 - static void ipipe_print_status(struct iss_ipipe_device *ipipe) 46 - { 47 - struct iss_device *iss = to_iss_device(ipipe); 48 - 49 - dev_dbg(iss->dev, "-------------IPIPE Register dump-------------\n"); 50 - 51 - IPIPE_PRINT_REGISTER(iss, SRC_EN); 52 - IPIPE_PRINT_REGISTER(iss, SRC_MODE); 53 - IPIPE_PRINT_REGISTER(iss, SRC_FMT); 54 - IPIPE_PRINT_REGISTER(iss, SRC_COL); 55 - IPIPE_PRINT_REGISTER(iss, SRC_VPS); 56 - IPIPE_PRINT_REGISTER(iss, SRC_VSZ); 57 - IPIPE_PRINT_REGISTER(iss, SRC_HPS); 58 - IPIPE_PRINT_REGISTER(iss, SRC_HSZ); 59 - IPIPE_PRINT_REGISTER(iss, GCK_MMR); 60 - IPIPE_PRINT_REGISTER(iss, YUV_PHS); 61 - 62 - dev_dbg(iss->dev, "-----------------------------------------------\n"); 63 - } 64 - 65 - /* 66 - * ipipe_enable - Enable/Disable IPIPE. 67 - * @enable: enable flag 68 - * 69 - */ 70 - static void ipipe_enable(struct iss_ipipe_device *ipipe, u8 enable) 71 - { 72 - struct iss_device *iss = to_iss_device(ipipe); 73 - 74 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_EN, 75 - IPIPE_SRC_EN_EN, enable ? IPIPE_SRC_EN_EN : 0); 76 - } 77 - 78 - /* ----------------------------------------------------------------------------- 79 - * Format- and pipeline-related configuration helpers 80 - */ 81 - 82 - static void ipipe_configure(struct iss_ipipe_device *ipipe) 83 - { 84 - struct iss_device *iss = to_iss_device(ipipe); 85 - struct v4l2_mbus_framefmt *format; 86 - 87 - /* IPIPE_PAD_SINK */ 88 - format = &ipipe->formats[IPIPE_PAD_SINK]; 89 - 90 - /* NOTE: Currently just supporting pipeline IN: RGB, OUT: YUV422 */ 91 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_FMT, 92 - IPIPE_SRC_FMT_RAW2YUV); 93 - 94 - /* Enable YUV444 -> YUV422 conversion */ 95 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_YUV_PHS, 96 - IPIPE_YUV_PHS_LPF); 97 - 98 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_VPS, 0); 99 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_HPS, 0); 100 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_VSZ, 101 - (format->height - 2) & IPIPE_SRC_VSZ_MASK); 102 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_HSZ, 103 - (format->width - 1) & IPIPE_SRC_HSZ_MASK); 104 - 105 - /* Ignore ipipeif_wrt signal, and operate on-the-fly. */ 106 - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_MODE, 107 - IPIPE_SRC_MODE_WRT | IPIPE_SRC_MODE_OST); 108 - 109 - /* HACK: Values tuned for Ducati SW (OV) */ 110 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_COL, 111 - IPIPE_SRC_COL_EE_B | IPIPE_SRC_COL_EO_GB | 112 - IPIPE_SRC_COL_OE_GR | IPIPE_SRC_COL_OO_R); 113 - 114 - /* IPIPE_PAD_SOURCE_VP */ 115 - format = &ipipe->formats[IPIPE_PAD_SOURCE_VP]; 116 - /* Do nothing? */ 117 - } 118 - 119 - /* ----------------------------------------------------------------------------- 120 - * V4L2 subdev operations 121 - */ 122 - 123 - /* 124 - * ipipe_set_stream - Enable/Disable streaming on the IPIPE module 125 - * @sd: ISP IPIPE V4L2 subdevice 126 - * @enable: Enable/disable stream 127 - */ 128 - static int ipipe_set_stream(struct v4l2_subdev *sd, int enable) 129 - { 130 - struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); 131 - struct iss_device *iss = to_iss_device(ipipe); 132 - int ret = 0; 133 - 134 - if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED) { 135 - if (enable == ISS_PIPELINE_STREAM_STOPPED) 136 - return 0; 137 - 138 - omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE); 139 - 140 - /* Enable clk_arm_g0 */ 141 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_GCK_MMR, 142 - IPIPE_GCK_MMR_REG); 143 - 144 - /* Enable clk_pix_g[3:0] */ 145 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_GCK_PIX, 146 - IPIPE_GCK_PIX_G3 | IPIPE_GCK_PIX_G2 | 147 - IPIPE_GCK_PIX_G1 | IPIPE_GCK_PIX_G0); 148 - } 149 - 150 - switch (enable) { 151 - case ISS_PIPELINE_STREAM_CONTINUOUS: 152 - 153 - ipipe_configure(ipipe); 154 - ipipe_print_status(ipipe); 155 - 156 - atomic_set(&ipipe->stopping, 0); 157 - ipipe_enable(ipipe, 1); 158 - break; 159 - 160 - case ISS_PIPELINE_STREAM_STOPPED: 161 - if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED) 162 - return 0; 163 - if (omap4iss_module_sync_idle(&sd->entity, &ipipe->wait, 164 - &ipipe->stopping)) 165 - ret = -ETIMEDOUT; 166 - 167 - ipipe_enable(ipipe, 0); 168 - omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE); 169 - break; 170 - } 171 - 172 - ipipe->state = enable; 173 - return ret; 174 - } 175 - 176 - static struct v4l2_mbus_framefmt * 177 - __ipipe_get_format(struct iss_ipipe_device *ipipe, 178 - struct v4l2_subdev_state *sd_state, 179 - unsigned int pad, 180 - enum v4l2_subdev_format_whence which) 181 - { 182 - if (which == V4L2_SUBDEV_FORMAT_TRY) 183 - return v4l2_subdev_state_get_format(sd_state, pad); 184 - 185 - return &ipipe->formats[pad]; 186 - } 187 - 188 - /* 189 - * ipipe_try_format - Try video format on a pad 190 - * @ipipe: ISS IPIPE device 191 - * @sd_state: V4L2 subdev state 192 - * @pad: Pad number 193 - * @fmt: Format 194 - */ 195 - static void 196 - ipipe_try_format(struct iss_ipipe_device *ipipe, 197 - struct v4l2_subdev_state *sd_state, 198 - unsigned int pad, 199 - struct v4l2_mbus_framefmt *fmt, 200 - enum v4l2_subdev_format_whence which) 201 - { 202 - struct v4l2_mbus_framefmt *format; 203 - unsigned int width = fmt->width; 204 - unsigned int height = fmt->height; 205 - unsigned int i; 206 - 207 - switch (pad) { 208 - case IPIPE_PAD_SINK: 209 - for (i = 0; i < ARRAY_SIZE(ipipe_fmts); i++) { 210 - if (fmt->code == ipipe_fmts[i]) 211 - break; 212 - } 213 - 214 - /* If not found, use SGRBG10 as default */ 215 - if (i >= ARRAY_SIZE(ipipe_fmts)) 216 - fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; 217 - 218 - /* Clamp the input size. */ 219 - fmt->width = clamp_t(u32, width, 1, 8192); 220 - fmt->height = clamp_t(u32, height, 1, 8192); 221 - fmt->colorspace = V4L2_COLORSPACE_SRGB; 222 - break; 223 - 224 - case IPIPE_PAD_SOURCE_VP: 225 - format = __ipipe_get_format(ipipe, sd_state, IPIPE_PAD_SINK, 226 - which); 227 - memcpy(fmt, format, sizeof(*fmt)); 228 - 229 - fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; 230 - fmt->width = clamp_t(u32, width, 32, fmt->width); 231 - fmt->height = clamp_t(u32, height, 32, fmt->height); 232 - fmt->colorspace = V4L2_COLORSPACE_JPEG; 233 - break; 234 - } 235 - 236 - fmt->field = V4L2_FIELD_NONE; 237 - } 238 - 239 - /* 240 - * ipipe_enum_mbus_code - Handle pixel format enumeration 241 - * @sd : pointer to v4l2 subdev structure 242 - * @sd_state: V4L2 subdev state 243 - * @code : pointer to v4l2_subdev_mbus_code_enum structure 244 - * return -EINVAL or zero on success 245 - */ 246 - static int ipipe_enum_mbus_code(struct v4l2_subdev *sd, 247 - struct v4l2_subdev_state *sd_state, 248 - struct v4l2_subdev_mbus_code_enum *code) 249 - { 250 - switch (code->pad) { 251 - case IPIPE_PAD_SINK: 252 - if (code->index >= ARRAY_SIZE(ipipe_fmts)) 253 - return -EINVAL; 254 - 255 - code->code = ipipe_fmts[code->index]; 256 - break; 257 - 258 - case IPIPE_PAD_SOURCE_VP: 259 - /* FIXME: Forced format conversion inside IPIPE ? */ 260 - if (code->index != 0) 261 - return -EINVAL; 262 - 263 - code->code = MEDIA_BUS_FMT_UYVY8_1X16; 264 - break; 265 - 266 - default: 267 - return -EINVAL; 268 - } 269 - 270 - return 0; 271 - } 272 - 273 - static int ipipe_enum_frame_size(struct v4l2_subdev *sd, 274 - struct v4l2_subdev_state *sd_state, 275 - struct v4l2_subdev_frame_size_enum *fse) 276 - { 277 - struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); 278 - struct v4l2_mbus_framefmt format; 279 - 280 - if (fse->index != 0) 281 - return -EINVAL; 282 - 283 - format.code = fse->code; 284 - format.width = 1; 285 - format.height = 1; 286 - ipipe_try_format(ipipe, sd_state, fse->pad, &format, fse->which); 287 - fse->min_width = format.width; 288 - fse->min_height = format.height; 289 - 290 - if (format.code != fse->code) 291 - return -EINVAL; 292 - 293 - format.code = fse->code; 294 - format.width = -1; 295 - format.height = -1; 296 - ipipe_try_format(ipipe, sd_state, fse->pad, &format, fse->which); 297 - fse->max_width = format.width; 298 - fse->max_height = format.height; 299 - 300 - return 0; 301 - } 302 - 303 - /* 304 - * ipipe_get_format - Retrieve the video format on a pad 305 - * @sd : ISP IPIPE V4L2 subdevice 306 - * @sd_state: V4L2 subdev state 307 - * @fmt: Format 308 - * 309 - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond 310 - * to the format type. 311 - */ 312 - static int ipipe_get_format(struct v4l2_subdev *sd, 313 - struct v4l2_subdev_state *sd_state, 314 - struct v4l2_subdev_format *fmt) 315 - { 316 - struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); 317 - struct v4l2_mbus_framefmt *format; 318 - 319 - format = __ipipe_get_format(ipipe, sd_state, fmt->pad, fmt->which); 320 - if (!format) 321 - return -EINVAL; 322 - 323 - fmt->format = *format; 324 - return 0; 325 - } 326 - 327 - /* 328 - * ipipe_set_format - Set the video format on a pad 329 - * @sd : ISP IPIPE V4L2 subdevice 330 - * @sd_state: V4L2 subdev state 331 - * @fmt: Format 332 - * 333 - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond 334 - * to the format type. 335 - */ 336 - static int ipipe_set_format(struct v4l2_subdev *sd, 337 - struct v4l2_subdev_state *sd_state, 338 - struct v4l2_subdev_format *fmt) 339 - { 340 - struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); 341 - struct v4l2_mbus_framefmt *format; 342 - 343 - format = __ipipe_get_format(ipipe, sd_state, fmt->pad, fmt->which); 344 - if (!format) 345 - return -EINVAL; 346 - 347 - ipipe_try_format(ipipe, sd_state, fmt->pad, &fmt->format, fmt->which); 348 - *format = fmt->format; 349 - 350 - /* Propagate the format from sink to source */ 351 - if (fmt->pad == IPIPE_PAD_SINK) { 352 - format = __ipipe_get_format(ipipe, sd_state, 353 - IPIPE_PAD_SOURCE_VP, 354 - fmt->which); 355 - *format = fmt->format; 356 - ipipe_try_format(ipipe, sd_state, IPIPE_PAD_SOURCE_VP, format, 357 - fmt->which); 358 - } 359 - 360 - return 0; 361 - } 362 - 363 - static int ipipe_link_validate(struct v4l2_subdev *sd, struct media_link *link, 364 - struct v4l2_subdev_format *source_fmt, 365 - struct v4l2_subdev_format *sink_fmt) 366 - { 367 - /* Check if the two ends match */ 368 - if (source_fmt->format.width != sink_fmt->format.width || 369 - source_fmt->format.height != sink_fmt->format.height) 370 - return -EPIPE; 371 - 372 - if (source_fmt->format.code != sink_fmt->format.code) 373 - return -EPIPE; 374 - 375 - return 0; 376 - } 377 - 378 - /* 379 - * ipipe_init_formats - Initialize formats on all pads 380 - * @sd: ISP IPIPE V4L2 subdevice 381 - * @fh: V4L2 subdev file handle 382 - * 383 - * Initialize all pad formats with default values. If fh is not NULL, try 384 - * formats are initialized on the file handle. Otherwise active formats are 385 - * initialized on the device. 386 - */ 387 - static int ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 388 - { 389 - struct v4l2_subdev_format format; 390 - 391 - memset(&format, 0, sizeof(format)); 392 - format.pad = IPIPE_PAD_SINK; 393 - format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; 394 - format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10; 395 - format.format.width = 4096; 396 - format.format.height = 4096; 397 - ipipe_set_format(sd, fh ? fh->state : NULL, &format); 398 - 399 - return 0; 400 - } 401 - 402 - /* V4L2 subdev video operations */ 403 - static const struct v4l2_subdev_video_ops ipipe_v4l2_video_ops = { 404 - .s_stream = ipipe_set_stream, 405 - }; 406 - 407 - /* V4L2 subdev pad operations */ 408 - static const struct v4l2_subdev_pad_ops ipipe_v4l2_pad_ops = { 409 - .enum_mbus_code = ipipe_enum_mbus_code, 410 - .enum_frame_size = ipipe_enum_frame_size, 411 - .get_fmt = ipipe_get_format, 412 - .set_fmt = ipipe_set_format, 413 - .link_validate = ipipe_link_validate, 414 - }; 415 - 416 - /* V4L2 subdev operations */ 417 - static const struct v4l2_subdev_ops ipipe_v4l2_ops = { 418 - .video = &ipipe_v4l2_video_ops, 419 - .pad = &ipipe_v4l2_pad_ops, 420 - }; 421 - 422 - /* V4L2 subdev internal operations */ 423 - static const struct v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = { 424 - .open = ipipe_init_formats, 425 - }; 426 - 427 - /* ----------------------------------------------------------------------------- 428 - * Media entity operations 429 - */ 430 - 431 - /* 432 - * ipipe_link_setup - Setup IPIPE connections 433 - * @entity: IPIPE media entity 434 - * @local: Pad at the local end of the link 435 - * @remote: Pad at the remote end of the link 436 - * @flags: Link flags 437 - * 438 - * return -EINVAL or zero on success 439 - */ 440 - static int ipipe_link_setup(struct media_entity *entity, 441 - const struct media_pad *local, 442 - const struct media_pad *remote, u32 flags) 443 - { 444 - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); 445 - struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); 446 - struct iss_device *iss = to_iss_device(ipipe); 447 - 448 - if (!is_media_entity_v4l2_subdev(remote->entity)) 449 - return -EINVAL; 450 - 451 - switch (local->index) { 452 - case IPIPE_PAD_SINK: 453 - /* Read from IPIPEIF. */ 454 - if (!(flags & MEDIA_LNK_FL_ENABLED)) { 455 - ipipe->input = IPIPE_INPUT_NONE; 456 - break; 457 - } 458 - 459 - if (ipipe->input != IPIPE_INPUT_NONE) 460 - return -EBUSY; 461 - 462 - if (remote->entity == &iss->ipipeif.subdev.entity) 463 - ipipe->input = IPIPE_INPUT_IPIPEIF; 464 - 465 - break; 466 - 467 - case IPIPE_PAD_SOURCE_VP: 468 - /* Send to RESIZER */ 469 - if (flags & MEDIA_LNK_FL_ENABLED) { 470 - if (ipipe->output & ~IPIPE_OUTPUT_VP) 471 - return -EBUSY; 472 - ipipe->output |= IPIPE_OUTPUT_VP; 473 - } else { 474 - ipipe->output &= ~IPIPE_OUTPUT_VP; 475 - } 476 - break; 477 - 478 - default: 479 - return -EINVAL; 480 - } 481 - 482 - return 0; 483 - } 484 - 485 - /* media operations */ 486 - static const struct media_entity_operations ipipe_media_ops = { 487 - .link_setup = ipipe_link_setup, 488 - .link_validate = v4l2_subdev_link_validate, 489 - }; 490 - 491 - /* 492 - * ipipe_init_entities - Initialize V4L2 subdev and media entity 493 - * @ipipe: ISS ISP IPIPE module 494 - * 495 - * Return 0 on success and a negative error code on failure. 496 - */ 497 - static int ipipe_init_entities(struct iss_ipipe_device *ipipe) 498 - { 499 - struct v4l2_subdev *sd = &ipipe->subdev; 500 - struct media_pad *pads = ipipe->pads; 501 - struct media_entity *me = &sd->entity; 502 - int ret; 503 - 504 - ipipe->input = IPIPE_INPUT_NONE; 505 - 506 - v4l2_subdev_init(sd, &ipipe_v4l2_ops); 507 - sd->internal_ops = &ipipe_v4l2_internal_ops; 508 - strscpy(sd->name, "OMAP4 ISS ISP IPIPE", sizeof(sd->name)); 509 - sd->grp_id = BIT(16); /* group ID for iss subdevs */ 510 - v4l2_set_subdevdata(sd, ipipe); 511 - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 512 - 513 - pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 514 - pads[IPIPE_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; 515 - 516 - me->ops = &ipipe_media_ops; 517 - ret = media_entity_pads_init(me, IPIPE_PADS_NUM, pads); 518 - if (ret < 0) 519 - return ret; 520 - 521 - ipipe_init_formats(sd, NULL); 522 - 523 - return 0; 524 - } 525 - 526 - void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe) 527 - { 528 - v4l2_device_unregister_subdev(&ipipe->subdev); 529 - } 530 - 531 - int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe, 532 - struct v4l2_device *vdev) 533 - { 534 - int ret; 535 - 536 - /* Register the subdev and video node. */ 537 - ret = v4l2_device_register_subdev(vdev, &ipipe->subdev); 538 - if (ret < 0) 539 - goto error; 540 - 541 - return 0; 542 - 543 - error: 544 - omap4iss_ipipe_unregister_entities(ipipe); 545 - return ret; 546 - } 547 - 548 - /* ----------------------------------------------------------------------------- 549 - * ISP IPIPE initialisation and cleanup 550 - */ 551 - 552 - /* 553 - * omap4iss_ipipe_init - IPIPE module initialization. 554 - * @iss: Device pointer specific to the OMAP4 ISS. 555 - * 556 - * TODO: Get the initialisation values from platform data. 557 - * 558 - * Return 0 on success or a negative error code otherwise. 559 - */ 560 - int omap4iss_ipipe_init(struct iss_device *iss) 561 - { 562 - struct iss_ipipe_device *ipipe = &iss->ipipe; 563 - 564 - ipipe->state = ISS_PIPELINE_STREAM_STOPPED; 565 - init_waitqueue_head(&ipipe->wait); 566 - 567 - return ipipe_init_entities(ipipe); 568 - } 569 - 570 - /* 571 - * omap4iss_ipipe_cleanup - IPIPE module cleanup. 572 - * @iss: Device pointer specific to the OMAP4 ISS. 573 - */ 574 - void omap4iss_ipipe_cleanup(struct iss_device *iss) 575 - { 576 - struct iss_ipipe_device *ipipe = &iss->ipipe; 577 - 578 - media_entity_cleanup(&ipipe->subdev.entity); 579 - }
-63
drivers/staging/media/omap4iss/iss_ipipe.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ */ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #ifndef OMAP4_ISS_IPIPE_H 11 - #define OMAP4_ISS_IPIPE_H 12 - 13 - #include "iss_video.h" 14 - 15 - enum ipipe_input_entity { 16 - IPIPE_INPUT_NONE, 17 - IPIPE_INPUT_IPIPEIF, 18 - }; 19 - 20 - #define IPIPE_OUTPUT_VP BIT(0) 21 - 22 - /* Sink and source IPIPE pads */ 23 - #define IPIPE_PAD_SINK 0 24 - #define IPIPE_PAD_SOURCE_VP 1 25 - #define IPIPE_PADS_NUM 2 26 - 27 - /* 28 - * struct iss_ipipe_device - Structure for the IPIPE module to store its own 29 - * information 30 - * @subdev: V4L2 subdevice 31 - * @pads: Sink and source media entity pads 32 - * @formats: Active video formats 33 - * @input: Active input 34 - * @output: Active outputs 35 - * @error: A hardware error occurred during capture 36 - * @state: Streaming state 37 - * @wait: Wait queue used to stop the module 38 - * @stopping: Stopping state 39 - */ 40 - struct iss_ipipe_device { 41 - struct v4l2_subdev subdev; 42 - struct media_pad pads[IPIPE_PADS_NUM]; 43 - struct v4l2_mbus_framefmt formats[IPIPE_PADS_NUM]; 44 - 45 - enum ipipe_input_entity input; 46 - unsigned int output; 47 - unsigned int error; 48 - 49 - enum iss_pipeline_stream_state state; 50 - wait_queue_head_t wait; 51 - atomic_t stopping; 52 - }; 53 - 54 - struct iss_device; 55 - 56 - int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe, 57 - struct v4l2_device *vdev); 58 - void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe); 59 - 60 - int omap4iss_ipipe_init(struct iss_device *iss); 61 - void omap4iss_ipipe_cleanup(struct iss_device *iss); 62 - 63 - #endif /* OMAP4_ISS_IPIPE_H */
-844
drivers/staging/media/omap4iss/iss_ipipeif.c
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #include <linux/module.h> 11 - #include <linux/uaccess.h> 12 - #include <linux/delay.h> 13 - #include <linux/device.h> 14 - #include <linux/dma-mapping.h> 15 - #include <linux/mm.h> 16 - #include <linux/sched.h> 17 - 18 - #include "iss.h" 19 - #include "iss_regs.h" 20 - #include "iss_ipipeif.h" 21 - 22 - static const unsigned int ipipeif_fmts[] = { 23 - MEDIA_BUS_FMT_SGRBG10_1X10, 24 - MEDIA_BUS_FMT_SRGGB10_1X10, 25 - MEDIA_BUS_FMT_SBGGR10_1X10, 26 - MEDIA_BUS_FMT_SGBRG10_1X10, 27 - MEDIA_BUS_FMT_UYVY8_1X16, 28 - MEDIA_BUS_FMT_YUYV8_1X16, 29 - }; 30 - 31 - /* 32 - * ipipeif_print_status - Print current IPIPEIF Module register values. 33 - * @ipipeif: Pointer to ISS ISP IPIPEIF device. 34 - * 35 - * Also prints other debug information stored in the IPIPEIF module. 36 - */ 37 - #define IPIPEIF_PRINT_REGISTER(iss, name)\ 38 - dev_dbg(iss->dev, "###IPIPEIF " #name "=0x%08x\n", \ 39 - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_##name)) 40 - 41 - #define ISIF_PRINT_REGISTER(iss, name)\ 42 - dev_dbg(iss->dev, "###ISIF " #name "=0x%08x\n", \ 43 - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_##name)) 44 - 45 - #define ISP5_PRINT_REGISTER(iss, name)\ 46 - dev_dbg(iss->dev, "###ISP5 " #name "=0x%08x\n", \ 47 - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_##name)) 48 - 49 - static void ipipeif_print_status(struct iss_ipipeif_device *ipipeif) 50 - { 51 - struct iss_device *iss = to_iss_device(ipipeif); 52 - 53 - dev_dbg(iss->dev, "-------------IPIPEIF Register dump-------------\n"); 54 - 55 - IPIPEIF_PRINT_REGISTER(iss, CFG1); 56 - IPIPEIF_PRINT_REGISTER(iss, CFG2); 57 - 58 - ISIF_PRINT_REGISTER(iss, SYNCEN); 59 - ISIF_PRINT_REGISTER(iss, CADU); 60 - ISIF_PRINT_REGISTER(iss, CADL); 61 - ISIF_PRINT_REGISTER(iss, MODESET); 62 - ISIF_PRINT_REGISTER(iss, CCOLP); 63 - ISIF_PRINT_REGISTER(iss, SPH); 64 - ISIF_PRINT_REGISTER(iss, LNH); 65 - ISIF_PRINT_REGISTER(iss, LNV); 66 - ISIF_PRINT_REGISTER(iss, VDINT(0)); 67 - ISIF_PRINT_REGISTER(iss, HSIZE); 68 - 69 - ISP5_PRINT_REGISTER(iss, SYSCONFIG); 70 - ISP5_PRINT_REGISTER(iss, CTRL); 71 - ISP5_PRINT_REGISTER(iss, IRQSTATUS(0)); 72 - ISP5_PRINT_REGISTER(iss, IRQENABLE_SET(0)); 73 - ISP5_PRINT_REGISTER(iss, IRQENABLE_CLR(0)); 74 - 75 - dev_dbg(iss->dev, "-----------------------------------------------\n"); 76 - } 77 - 78 - static void ipipeif_write_enable(struct iss_ipipeif_device *ipipeif, u8 enable) 79 - { 80 - struct iss_device *iss = to_iss_device(ipipeif); 81 - 82 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SYNCEN, 83 - ISIF_SYNCEN_DWEN, enable ? ISIF_SYNCEN_DWEN : 0); 84 - } 85 - 86 - /* 87 - * ipipeif_enable - Enable/Disable IPIPEIF. 88 - * @enable: enable flag 89 - * 90 - */ 91 - static void ipipeif_enable(struct iss_ipipeif_device *ipipeif, u8 enable) 92 - { 93 - struct iss_device *iss = to_iss_device(ipipeif); 94 - 95 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SYNCEN, 96 - ISIF_SYNCEN_SYEN, enable ? ISIF_SYNCEN_SYEN : 0); 97 - } 98 - 99 - /* ----------------------------------------------------------------------------- 100 - * Format- and pipeline-related configuration helpers 101 - */ 102 - 103 - /* 104 - * ipipeif_set_outaddr - Set memory address to save output image 105 - * @ipipeif: Pointer to ISP IPIPEIF device. 106 - * @addr: 32-bit memory address aligned on 32 byte boundary. 107 - * 108 - * Sets the memory address where the output will be saved. 109 - */ 110 - static void ipipeif_set_outaddr(struct iss_ipipeif_device *ipipeif, u32 addr) 111 - { 112 - struct iss_device *iss = to_iss_device(ipipeif); 113 - 114 - /* Save address split in Base Address H & L */ 115 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CADU, 116 - (addr >> (16 + 5)) & ISIF_CADU_MASK); 117 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CADL, 118 - (addr >> 5) & ISIF_CADL_MASK); 119 - } 120 - 121 - static void ipipeif_configure(struct iss_ipipeif_device *ipipeif) 122 - { 123 - struct iss_device *iss = to_iss_device(ipipeif); 124 - const struct iss_format_info *info; 125 - struct v4l2_mbus_framefmt *format; 126 - u32 isif_ccolp = 0; 127 - 128 - omap4iss_configure_bridge(iss, ipipeif->input); 129 - 130 - /* IPIPEIF_PAD_SINK */ 131 - format = &ipipeif->formats[IPIPEIF_PAD_SINK]; 132 - 133 - /* IPIPEIF with YUV422 input from ISIF */ 134 - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG1, 135 - IPIPEIF_CFG1_INPSRC1_MASK | IPIPEIF_CFG1_INPSRC2_MASK); 136 - 137 - /* Select ISIF/IPIPEIF input format */ 138 - switch (format->code) { 139 - case MEDIA_BUS_FMT_UYVY8_1X16: 140 - case MEDIA_BUS_FMT_YUYV8_1X16: 141 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_MODESET, 142 - ISIF_MODESET_CCDMD | ISIF_MODESET_INPMOD_MASK | 143 - ISIF_MODESET_CCDW_MASK, 144 - ISIF_MODESET_INPMOD_YCBCR16); 145 - 146 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG2, 147 - IPIPEIF_CFG2_YUV8, IPIPEIF_CFG2_YUV16); 148 - 149 - break; 150 - case MEDIA_BUS_FMT_SGRBG10_1X10: 151 - isif_ccolp = ISIF_CCOLP_CP0_F0_GR | 152 - ISIF_CCOLP_CP1_F0_R | 153 - ISIF_CCOLP_CP2_F0_B | 154 - ISIF_CCOLP_CP3_F0_GB; 155 - goto cont_raw; 156 - case MEDIA_BUS_FMT_SRGGB10_1X10: 157 - isif_ccolp = ISIF_CCOLP_CP0_F0_R | 158 - ISIF_CCOLP_CP1_F0_GR | 159 - ISIF_CCOLP_CP2_F0_GB | 160 - ISIF_CCOLP_CP3_F0_B; 161 - goto cont_raw; 162 - case MEDIA_BUS_FMT_SBGGR10_1X10: 163 - isif_ccolp = ISIF_CCOLP_CP0_F0_B | 164 - ISIF_CCOLP_CP1_F0_GB | 165 - ISIF_CCOLP_CP2_F0_GR | 166 - ISIF_CCOLP_CP3_F0_R; 167 - goto cont_raw; 168 - case MEDIA_BUS_FMT_SGBRG10_1X10: 169 - isif_ccolp = ISIF_CCOLP_CP0_F0_GB | 170 - ISIF_CCOLP_CP1_F0_B | 171 - ISIF_CCOLP_CP2_F0_R | 172 - ISIF_CCOLP_CP3_F0_GR; 173 - cont_raw: 174 - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG2, 175 - IPIPEIF_CFG2_YUV16); 176 - 177 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_MODESET, 178 - ISIF_MODESET_CCDMD | ISIF_MODESET_INPMOD_MASK | 179 - ISIF_MODESET_CCDW_MASK, ISIF_MODESET_INPMOD_RAW | 180 - ISIF_MODESET_CCDW_2BIT); 181 - 182 - info = omap4iss_video_format_info(format->code); 183 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CGAMMAWD, 184 - ISIF_CGAMMAWD_GWDI_MASK, 185 - ISIF_CGAMMAWD_GWDI(info->bpp)); 186 - 187 - /* Set RAW Bayer pattern */ 188 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CCOLP, 189 - isif_ccolp); 190 - break; 191 - } 192 - 193 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SPH, 0 & ISIF_SPH_MASK); 194 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_LNH, 195 - (format->width - 1) & ISIF_LNH_MASK); 196 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_LNV, 197 - (format->height - 1) & ISIF_LNV_MASK); 198 - 199 - /* Generate ISIF0 on the last line of the image */ 200 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_VDINT(0), 201 - format->height - 1); 202 - 203 - /* IPIPEIF_PAD_SOURCE_ISIF_SF */ 204 - format = &ipipeif->formats[IPIPEIF_PAD_SOURCE_ISIF_SF]; 205 - 206 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_HSIZE, 207 - (ipipeif->video_out.bpl_value >> 5) & 208 - ISIF_HSIZE_HSIZE_MASK); 209 - 210 - /* IPIPEIF_PAD_SOURCE_VP */ 211 - /* Do nothing? */ 212 - } 213 - 214 - /* ----------------------------------------------------------------------------- 215 - * Interrupt handling 216 - */ 217 - 218 - static void ipipeif_isr_buffer(struct iss_ipipeif_device *ipipeif) 219 - { 220 - struct iss_buffer *buffer; 221 - 222 - /* The ISIF generates VD0 interrupts even when writes are disabled. 223 - * deal with it anyway). Disabling the ISIF when no buffer is available 224 - * is thus not be enough, we need to handle the situation explicitly. 225 - */ 226 - if (list_empty(&ipipeif->video_out.dmaqueue)) 227 - return; 228 - 229 - ipipeif_write_enable(ipipeif, 0); 230 - 231 - buffer = omap4iss_video_buffer_next(&ipipeif->video_out); 232 - if (!buffer) 233 - return; 234 - 235 - ipipeif_set_outaddr(ipipeif, buffer->iss_addr); 236 - 237 - ipipeif_write_enable(ipipeif, 1); 238 - } 239 - 240 - /* 241 - * omap4iss_ipipeif_isr - Configure ipipeif during interframe time. 242 - * @ipipeif: Pointer to ISP IPIPEIF device. 243 - * @events: IPIPEIF events 244 - */ 245 - void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events) 246 - { 247 - if (omap4iss_module_sync_is_stopping(&ipipeif->wait, 248 - &ipipeif->stopping)) 249 - return; 250 - 251 - if ((events & ISP5_IRQ_ISIF_INT(0)) && 252 - (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)) 253 - ipipeif_isr_buffer(ipipeif); 254 - } 255 - 256 - /* ----------------------------------------------------------------------------- 257 - * ISP video operations 258 - */ 259 - 260 - static int ipipeif_video_queue(struct iss_video *video, 261 - struct iss_buffer *buffer) 262 - { 263 - struct iss_ipipeif_device *ipipeif = container_of(video, 264 - struct iss_ipipeif_device, video_out); 265 - 266 - if (!(ipipeif->output & IPIPEIF_OUTPUT_MEMORY)) 267 - return -ENODEV; 268 - 269 - ipipeif_set_outaddr(ipipeif, buffer->iss_addr); 270 - 271 - /* 272 - * If streaming was enabled before there was a buffer queued 273 - * or underrun happened in the ISR, the hardware was not enabled 274 - * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set. 275 - * Enable it now. 276 - */ 277 - if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { 278 - if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) 279 - ipipeif_write_enable(ipipeif, 1); 280 - ipipeif_enable(ipipeif, 1); 281 - iss_video_dmaqueue_flags_clr(video); 282 - } 283 - 284 - return 0; 285 - } 286 - 287 - static const struct iss_video_operations ipipeif_video_ops = { 288 - .queue = ipipeif_video_queue, 289 - }; 290 - 291 - /* ----------------------------------------------------------------------------- 292 - * V4L2 subdev operations 293 - */ 294 - 295 - #define IPIPEIF_DRV_SUBCLK_MASK (OMAP4_ISS_ISP_SUBCLK_IPIPEIF |\ 296 - OMAP4_ISS_ISP_SUBCLK_ISIF) 297 - /* 298 - * ipipeif_set_stream - Enable/Disable streaming on the IPIPEIF module 299 - * @sd: ISP IPIPEIF V4L2 subdevice 300 - * @enable: Enable/disable stream 301 - */ 302 - static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable) 303 - { 304 - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); 305 - struct iss_device *iss = to_iss_device(ipipeif); 306 - struct iss_video *video_out = &ipipeif->video_out; 307 - int ret = 0; 308 - 309 - if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED) { 310 - if (enable == ISS_PIPELINE_STREAM_STOPPED) 311 - return 0; 312 - 313 - omap4iss_isp_subclk_enable(iss, IPIPEIF_DRV_SUBCLK_MASK); 314 - } 315 - 316 - switch (enable) { 317 - case ISS_PIPELINE_STREAM_CONTINUOUS: 318 - 319 - ipipeif_configure(ipipeif); 320 - ipipeif_print_status(ipipeif); 321 - 322 - /* 323 - * When outputting to memory with no buffer available, let the 324 - * buffer queue handler start the hardware. A DMA queue flag 325 - * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is 326 - * a buffer available. 327 - */ 328 - if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY && 329 - !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED)) 330 - break; 331 - 332 - atomic_set(&ipipeif->stopping, 0); 333 - if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) 334 - ipipeif_write_enable(ipipeif, 1); 335 - ipipeif_enable(ipipeif, 1); 336 - iss_video_dmaqueue_flags_clr(video_out); 337 - break; 338 - 339 - case ISS_PIPELINE_STREAM_STOPPED: 340 - if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED) 341 - return 0; 342 - if (omap4iss_module_sync_idle(&sd->entity, &ipipeif->wait, 343 - &ipipeif->stopping)) 344 - ret = -ETIMEDOUT; 345 - 346 - if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) 347 - ipipeif_write_enable(ipipeif, 0); 348 - ipipeif_enable(ipipeif, 0); 349 - omap4iss_isp_subclk_disable(iss, IPIPEIF_DRV_SUBCLK_MASK); 350 - iss_video_dmaqueue_flags_clr(video_out); 351 - break; 352 - } 353 - 354 - ipipeif->state = enable; 355 - return ret; 356 - } 357 - 358 - static struct v4l2_mbus_framefmt * 359 - __ipipeif_get_format(struct iss_ipipeif_device *ipipeif, 360 - struct v4l2_subdev_state *sd_state, unsigned int pad, 361 - enum v4l2_subdev_format_whence which) 362 - { 363 - if (which == V4L2_SUBDEV_FORMAT_TRY) 364 - return v4l2_subdev_state_get_format(sd_state, pad); 365 - return &ipipeif->formats[pad]; 366 - } 367 - 368 - /* 369 - * ipipeif_try_format - Try video format on a pad 370 - * @ipipeif: ISS IPIPEIF device 371 - * @sd_state: V4L2 subdev state 372 - * @pad: Pad number 373 - * @fmt: Format 374 - */ 375 - static void 376 - ipipeif_try_format(struct iss_ipipeif_device *ipipeif, 377 - struct v4l2_subdev_state *sd_state, unsigned int pad, 378 - struct v4l2_mbus_framefmt *fmt, 379 - enum v4l2_subdev_format_whence which) 380 - { 381 - struct v4l2_mbus_framefmt *format; 382 - unsigned int width = fmt->width; 383 - unsigned int height = fmt->height; 384 - unsigned int i; 385 - 386 - switch (pad) { 387 - case IPIPEIF_PAD_SINK: 388 - /* TODO: If the IPIPEIF output formatter pad is connected 389 - * directly to the resizer, only YUV formats can be used. 390 - */ 391 - for (i = 0; i < ARRAY_SIZE(ipipeif_fmts); i++) { 392 - if (fmt->code == ipipeif_fmts[i]) 393 - break; 394 - } 395 - 396 - /* If not found, use SGRBG10 as default */ 397 - if (i >= ARRAY_SIZE(ipipeif_fmts)) 398 - fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; 399 - 400 - /* Clamp the input size. */ 401 - fmt->width = clamp_t(u32, width, 1, 8192); 402 - fmt->height = clamp_t(u32, height, 1, 8192); 403 - break; 404 - 405 - case IPIPEIF_PAD_SOURCE_ISIF_SF: 406 - format = __ipipeif_get_format(ipipeif, sd_state, 407 - IPIPEIF_PAD_SINK, 408 - which); 409 - memcpy(fmt, format, sizeof(*fmt)); 410 - 411 - /* The data formatter truncates the number of horizontal output 412 - * pixels to a multiple of 16. To avoid clipping data, allow 413 - * callers to request an output size bigger than the input size 414 - * up to the nearest multiple of 16. 415 - */ 416 - fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15); 417 - fmt->width &= ~15; 418 - fmt->height = clamp_t(u32, height, 32, fmt->height); 419 - break; 420 - 421 - case IPIPEIF_PAD_SOURCE_VP: 422 - format = __ipipeif_get_format(ipipeif, sd_state, 423 - IPIPEIF_PAD_SINK, 424 - which); 425 - memcpy(fmt, format, sizeof(*fmt)); 426 - 427 - fmt->width = clamp_t(u32, width, 32, fmt->width); 428 - fmt->height = clamp_t(u32, height, 32, fmt->height); 429 - break; 430 - } 431 - 432 - /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is 433 - * stored on 2 bytes. 434 - */ 435 - fmt->colorspace = V4L2_COLORSPACE_SRGB; 436 - fmt->field = V4L2_FIELD_NONE; 437 - } 438 - 439 - /* 440 - * ipipeif_enum_mbus_code - Handle pixel format enumeration 441 - * @sd : pointer to v4l2 subdev structure 442 - * @sd_state: V4L2 subdev state 443 - * @code : pointer to v4l2_subdev_mbus_code_enum structure 444 - * return -EINVAL or zero on success 445 - */ 446 - static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd, 447 - struct v4l2_subdev_state *sd_state, 448 - struct v4l2_subdev_mbus_code_enum *code) 449 - { 450 - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); 451 - struct v4l2_mbus_framefmt *format; 452 - 453 - switch (code->pad) { 454 - case IPIPEIF_PAD_SINK: 455 - if (code->index >= ARRAY_SIZE(ipipeif_fmts)) 456 - return -EINVAL; 457 - 458 - code->code = ipipeif_fmts[code->index]; 459 - break; 460 - 461 - case IPIPEIF_PAD_SOURCE_ISIF_SF: 462 - case IPIPEIF_PAD_SOURCE_VP: 463 - /* No format conversion inside IPIPEIF */ 464 - if (code->index != 0) 465 - return -EINVAL; 466 - 467 - format = __ipipeif_get_format(ipipeif, sd_state, 468 - IPIPEIF_PAD_SINK, 469 - code->which); 470 - 471 - code->code = format->code; 472 - break; 473 - 474 - default: 475 - return -EINVAL; 476 - } 477 - 478 - return 0; 479 - } 480 - 481 - static int ipipeif_enum_frame_size(struct v4l2_subdev *sd, 482 - struct v4l2_subdev_state *sd_state, 483 - struct v4l2_subdev_frame_size_enum *fse) 484 - { 485 - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); 486 - struct v4l2_mbus_framefmt format; 487 - 488 - if (fse->index != 0) 489 - return -EINVAL; 490 - 491 - format.code = fse->code; 492 - format.width = 1; 493 - format.height = 1; 494 - ipipeif_try_format(ipipeif, sd_state, fse->pad, &format, fse->which); 495 - fse->min_width = format.width; 496 - fse->min_height = format.height; 497 - 498 - if (format.code != fse->code) 499 - return -EINVAL; 500 - 501 - format.code = fse->code; 502 - format.width = -1; 503 - format.height = -1; 504 - ipipeif_try_format(ipipeif, sd_state, fse->pad, &format, fse->which); 505 - fse->max_width = format.width; 506 - fse->max_height = format.height; 507 - 508 - return 0; 509 - } 510 - 511 - /* 512 - * ipipeif_get_format - Retrieve the video format on a pad 513 - * @sd : ISP IPIPEIF V4L2 subdevice 514 - * @sd_state: V4L2 subdev state 515 - * @fmt: Format 516 - * 517 - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond 518 - * to the format type. 519 - */ 520 - static int ipipeif_get_format(struct v4l2_subdev *sd, 521 - struct v4l2_subdev_state *sd_state, 522 - struct v4l2_subdev_format *fmt) 523 - { 524 - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); 525 - struct v4l2_mbus_framefmt *format; 526 - 527 - format = __ipipeif_get_format(ipipeif, sd_state, fmt->pad, fmt->which); 528 - if (!format) 529 - return -EINVAL; 530 - 531 - fmt->format = *format; 532 - return 0; 533 - } 534 - 535 - /* 536 - * ipipeif_set_format - Set the video format on a pad 537 - * @sd : ISP IPIPEIF V4L2 subdevice 538 - * @sd_state: V4L2 subdev state 539 - * @fmt: Format 540 - * 541 - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond 542 - * to the format type. 543 - */ 544 - static int ipipeif_set_format(struct v4l2_subdev *sd, 545 - struct v4l2_subdev_state *sd_state, 546 - struct v4l2_subdev_format *fmt) 547 - { 548 - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); 549 - struct v4l2_mbus_framefmt *format; 550 - 551 - format = __ipipeif_get_format(ipipeif, sd_state, fmt->pad, fmt->which); 552 - if (!format) 553 - return -EINVAL; 554 - 555 - ipipeif_try_format(ipipeif, sd_state, fmt->pad, &fmt->format, 556 - fmt->which); 557 - *format = fmt->format; 558 - 559 - /* Propagate the format from sink to source */ 560 - if (fmt->pad == IPIPEIF_PAD_SINK) { 561 - format = __ipipeif_get_format(ipipeif, sd_state, 562 - IPIPEIF_PAD_SOURCE_ISIF_SF, 563 - fmt->which); 564 - *format = fmt->format; 565 - ipipeif_try_format(ipipeif, sd_state, 566 - IPIPEIF_PAD_SOURCE_ISIF_SF, 567 - format, fmt->which); 568 - 569 - format = __ipipeif_get_format(ipipeif, sd_state, 570 - IPIPEIF_PAD_SOURCE_VP, 571 - fmt->which); 572 - *format = fmt->format; 573 - ipipeif_try_format(ipipeif, sd_state, IPIPEIF_PAD_SOURCE_VP, 574 - format, 575 - fmt->which); 576 - } 577 - 578 - return 0; 579 - } 580 - 581 - static int ipipeif_link_validate(struct v4l2_subdev *sd, 582 - struct media_link *link, 583 - struct v4l2_subdev_format *source_fmt, 584 - struct v4l2_subdev_format *sink_fmt) 585 - { 586 - /* Check if the two ends match */ 587 - if (source_fmt->format.width != sink_fmt->format.width || 588 - source_fmt->format.height != sink_fmt->format.height) 589 - return -EPIPE; 590 - 591 - if (source_fmt->format.code != sink_fmt->format.code) 592 - return -EPIPE; 593 - 594 - return 0; 595 - } 596 - 597 - /* 598 - * ipipeif_init_formats - Initialize formats on all pads 599 - * @sd: ISP IPIPEIF V4L2 subdevice 600 - * @fh: V4L2 subdev file handle 601 - * 602 - * Initialize all pad formats with default values. If fh is not NULL, try 603 - * formats are initialized on the file handle. Otherwise active formats are 604 - * initialized on the device. 605 - */ 606 - static int ipipeif_init_formats(struct v4l2_subdev *sd, 607 - struct v4l2_subdev_fh *fh) 608 - { 609 - struct v4l2_subdev_format format; 610 - 611 - memset(&format, 0, sizeof(format)); 612 - format.pad = IPIPEIF_PAD_SINK; 613 - format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; 614 - format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10; 615 - format.format.width = 4096; 616 - format.format.height = 4096; 617 - ipipeif_set_format(sd, fh ? fh->state : NULL, &format); 618 - 619 - return 0; 620 - } 621 - 622 - /* V4L2 subdev video operations */ 623 - static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = { 624 - .s_stream = ipipeif_set_stream, 625 - }; 626 - 627 - /* V4L2 subdev pad operations */ 628 - static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = { 629 - .enum_mbus_code = ipipeif_enum_mbus_code, 630 - .enum_frame_size = ipipeif_enum_frame_size, 631 - .get_fmt = ipipeif_get_format, 632 - .set_fmt = ipipeif_set_format, 633 - .link_validate = ipipeif_link_validate, 634 - }; 635 - 636 - /* V4L2 subdev operations */ 637 - static const struct v4l2_subdev_ops ipipeif_v4l2_ops = { 638 - .video = &ipipeif_v4l2_video_ops, 639 - .pad = &ipipeif_v4l2_pad_ops, 640 - }; 641 - 642 - /* V4L2 subdev internal operations */ 643 - static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = { 644 - .open = ipipeif_init_formats, 645 - }; 646 - 647 - /* ----------------------------------------------------------------------------- 648 - * Media entity operations 649 - */ 650 - 651 - /* 652 - * ipipeif_link_setup - Setup IPIPEIF connections 653 - * @entity: IPIPEIF media entity 654 - * @local: Pad at the local end of the link 655 - * @remote: Pad at the remote end of the link 656 - * @flags: Link flags 657 - * 658 - * return -EINVAL or zero on success 659 - */ 660 - static int ipipeif_link_setup(struct media_entity *entity, 661 - const struct media_pad *local, 662 - const struct media_pad *remote, u32 flags) 663 - { 664 - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); 665 - struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); 666 - struct iss_device *iss = to_iss_device(ipipeif); 667 - unsigned int index = local->index; 668 - 669 - /* FIXME: this is actually a hack! */ 670 - if (is_media_entity_v4l2_subdev(remote->entity)) 671 - index |= 2 << 16; 672 - 673 - switch (index) { 674 - case IPIPEIF_PAD_SINK | 2 << 16: 675 - /* Read from the sensor CSI2a or CSI2b. */ 676 - if (!(flags & MEDIA_LNK_FL_ENABLED)) { 677 - ipipeif->input = IPIPEIF_INPUT_NONE; 678 - break; 679 - } 680 - 681 - if (ipipeif->input != IPIPEIF_INPUT_NONE) 682 - return -EBUSY; 683 - 684 - if (remote->entity == &iss->csi2a.subdev.entity) 685 - ipipeif->input = IPIPEIF_INPUT_CSI2A; 686 - else if (remote->entity == &iss->csi2b.subdev.entity) 687 - ipipeif->input = IPIPEIF_INPUT_CSI2B; 688 - 689 - break; 690 - 691 - case IPIPEIF_PAD_SOURCE_ISIF_SF: 692 - /* Write to memory */ 693 - if (flags & MEDIA_LNK_FL_ENABLED) { 694 - if (ipipeif->output & ~IPIPEIF_OUTPUT_MEMORY) 695 - return -EBUSY; 696 - ipipeif->output |= IPIPEIF_OUTPUT_MEMORY; 697 - } else { 698 - ipipeif->output &= ~IPIPEIF_OUTPUT_MEMORY; 699 - } 700 - break; 701 - 702 - case IPIPEIF_PAD_SOURCE_VP | 2 << 16: 703 - /* Send to IPIPE/RESIZER */ 704 - if (flags & MEDIA_LNK_FL_ENABLED) { 705 - if (ipipeif->output & ~IPIPEIF_OUTPUT_VP) 706 - return -EBUSY; 707 - ipipeif->output |= IPIPEIF_OUTPUT_VP; 708 - } else { 709 - ipipeif->output &= ~IPIPEIF_OUTPUT_VP; 710 - } 711 - break; 712 - 713 - default: 714 - return -EINVAL; 715 - } 716 - 717 - return 0; 718 - } 719 - 720 - /* media operations */ 721 - static const struct media_entity_operations ipipeif_media_ops = { 722 - .link_setup = ipipeif_link_setup, 723 - .link_validate = v4l2_subdev_link_validate, 724 - }; 725 - 726 - /* 727 - * ipipeif_init_entities - Initialize V4L2 subdev and media entity 728 - * @ipipeif: ISS ISP IPIPEIF module 729 - * 730 - * Return 0 on success and a negative error code on failure. 731 - */ 732 - static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif) 733 - { 734 - struct v4l2_subdev *sd = &ipipeif->subdev; 735 - struct media_pad *pads = ipipeif->pads; 736 - struct media_entity *me = &sd->entity; 737 - int ret; 738 - 739 - ipipeif->input = IPIPEIF_INPUT_NONE; 740 - 741 - v4l2_subdev_init(sd, &ipipeif_v4l2_ops); 742 - sd->internal_ops = &ipipeif_v4l2_internal_ops; 743 - strscpy(sd->name, "OMAP4 ISS ISP IPIPEIF", sizeof(sd->name)); 744 - sd->grp_id = BIT(16); /* group ID for iss subdevs */ 745 - v4l2_set_subdevdata(sd, ipipeif); 746 - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 747 - 748 - pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 749 - pads[IPIPEIF_PAD_SOURCE_ISIF_SF].flags = MEDIA_PAD_FL_SOURCE; 750 - pads[IPIPEIF_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; 751 - 752 - me->ops = &ipipeif_media_ops; 753 - ret = media_entity_pads_init(me, IPIPEIF_PADS_NUM, pads); 754 - if (ret < 0) 755 - return ret; 756 - 757 - ipipeif_init_formats(sd, NULL); 758 - 759 - ipipeif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 760 - ipipeif->video_out.ops = &ipipeif_video_ops; 761 - ipipeif->video_out.iss = to_iss_device(ipipeif); 762 - ipipeif->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; 763 - ipipeif->video_out.bpl_alignment = 32; 764 - ipipeif->video_out.bpl_zero_padding = 1; 765 - ipipeif->video_out.bpl_max = 0x1ffe0; 766 - 767 - return omap4iss_video_init(&ipipeif->video_out, "ISP IPIPEIF"); 768 - } 769 - 770 - void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif) 771 - { 772 - v4l2_device_unregister_subdev(&ipipeif->subdev); 773 - omap4iss_video_unregister(&ipipeif->video_out); 774 - } 775 - 776 - int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif, 777 - struct v4l2_device *vdev) 778 - { 779 - int ret; 780 - 781 - /* Register the subdev and video node. */ 782 - ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev); 783 - if (ret < 0) 784 - goto error; 785 - 786 - ret = omap4iss_video_register(&ipipeif->video_out, vdev); 787 - if (ret < 0) 788 - goto error; 789 - 790 - return 0; 791 - 792 - error: 793 - omap4iss_ipipeif_unregister_entities(ipipeif); 794 - return ret; 795 - } 796 - 797 - /* ----------------------------------------------------------------------------- 798 - * ISP IPIPEIF initialisation and cleanup 799 - */ 800 - 801 - /* 802 - * omap4iss_ipipeif_init - IPIPEIF module initialization. 803 - * @iss: Device pointer specific to the OMAP4 ISS. 804 - * 805 - * TODO: Get the initialisation values from platform data. 806 - * 807 - * Return 0 on success or a negative error code otherwise. 808 - */ 809 - int omap4iss_ipipeif_init(struct iss_device *iss) 810 - { 811 - struct iss_ipipeif_device *ipipeif = &iss->ipipeif; 812 - 813 - ipipeif->state = ISS_PIPELINE_STREAM_STOPPED; 814 - init_waitqueue_head(&ipipeif->wait); 815 - 816 - return ipipeif_init_entities(ipipeif); 817 - } 818 - 819 - /* 820 - * omap4iss_ipipeif_create_links() - IPIPEIF pads links creation 821 - * @iss: Pointer to ISS device 822 - * 823 - * return negative error code or zero on success 824 - */ 825 - int omap4iss_ipipeif_create_links(struct iss_device *iss) 826 - { 827 - struct iss_ipipeif_device *ipipeif = &iss->ipipeif; 828 - 829 - /* Connect the IPIPEIF subdev to the video node. */ 830 - return media_create_pad_link(&ipipeif->subdev.entity, 831 - IPIPEIF_PAD_SOURCE_ISIF_SF, 832 - &ipipeif->video_out.video.entity, 0, 0); 833 - } 834 - 835 - /* 836 - * omap4iss_ipipeif_cleanup - IPIPEIF module cleanup. 837 - * @iss: Device pointer specific to the OMAP4 ISS. 838 - */ 839 - void omap4iss_ipipeif_cleanup(struct iss_device *iss) 840 - { 841 - struct iss_ipipeif_device *ipipeif = &iss->ipipeif; 842 - 843 - media_entity_cleanup(&ipipeif->subdev.entity); 844 - }
-89
drivers/staging/media/omap4iss/iss_ipipeif.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ */ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #ifndef OMAP4_ISS_IPIPEIF_H 11 - #define OMAP4_ISS_IPIPEIF_H 12 - 13 - #include "iss_video.h" 14 - 15 - enum ipipeif_input_entity { 16 - IPIPEIF_INPUT_NONE, 17 - IPIPEIF_INPUT_CSI2A, 18 - IPIPEIF_INPUT_CSI2B 19 - }; 20 - 21 - #define IPIPEIF_OUTPUT_MEMORY BIT(0) 22 - #define IPIPEIF_OUTPUT_VP BIT(1) 23 - 24 - /* Sink and source IPIPEIF pads */ 25 - #define IPIPEIF_PAD_SINK 0 26 - #define IPIPEIF_PAD_SOURCE_ISIF_SF 1 27 - #define IPIPEIF_PAD_SOURCE_VP 2 28 - #define IPIPEIF_PADS_NUM 3 29 - 30 - /* 31 - * struct iss_ipipeif_device - Structure for the IPIPEIF module to store its own 32 - * information 33 - * @subdev: V4L2 subdevice 34 - * @pads: Sink and source media entity pads 35 - * @formats: Active video formats 36 - * @input: Active input 37 - * @output: Active outputs 38 - * @video_out: Output video node 39 - * @error: A hardware error occurred during capture 40 - * @alaw: A-law compression enabled (1) or disabled (0) 41 - * @lpf: Low pass filter enabled (1) or disabled (0) 42 - * @obclamp: Optical-black clamp enabled (1) or disabled (0) 43 - * @fpc_en: Faulty pixels correction enabled (1) or disabled (0) 44 - * @blcomp: Black level compensation configuration 45 - * @clamp: Optical-black or digital clamp configuration 46 - * @fpc: Faulty pixels correction configuration 47 - * @lsc: Lens shading compensation configuration 48 - * @update: Bitmask of controls to update during the next interrupt 49 - * @shadow_update: Controls update in progress by userspace 50 - * @syncif: Interface synchronization configuration 51 - * @vpcfg: Video port configuration 52 - * @underrun: A buffer underrun occurred and a new buffer has been queued 53 - * @state: Streaming state 54 - * @lock: Serializes shadow_update with interrupt handler 55 - * @wait: Wait queue used to stop the module 56 - * @stopping: Stopping state 57 - * @ioctl_lock: Serializes ioctl calls and LSC requests freeing 58 - */ 59 - struct iss_ipipeif_device { 60 - struct v4l2_subdev subdev; 61 - struct media_pad pads[IPIPEIF_PADS_NUM]; 62 - struct v4l2_mbus_framefmt formats[IPIPEIF_PADS_NUM]; 63 - 64 - enum ipipeif_input_entity input; 65 - unsigned int output; 66 - struct iss_video video_out; 67 - unsigned int error; 68 - 69 - enum iss_pipeline_stream_state state; 70 - wait_queue_head_t wait; 71 - atomic_t stopping; 72 - }; 73 - 74 - struct iss_device; 75 - 76 - int omap4iss_ipipeif_init(struct iss_device *iss); 77 - int omap4iss_ipipeif_create_links(struct iss_device *iss); 78 - void omap4iss_ipipeif_cleanup(struct iss_device *iss); 79 - int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif, 80 - struct v4l2_device *vdev); 81 - void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif); 82 - 83 - int omap4iss_ipipeif_busy(struct iss_ipipeif_device *ipipeif); 84 - void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events); 85 - void omap4iss_ipipeif_restore_context(struct iss_device *iss); 86 - void omap4iss_ipipeif_max_rate(struct iss_ipipeif_device *ipipeif, 87 - unsigned int *max_rate); 88 - 89 - #endif /* OMAP4_ISS_IPIPEIF_H */
-899
drivers/staging/media/omap4iss/iss_regs.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ */ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - Register defines 4 - * 5 - * Copyright (C) 2012 Texas Instruments. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #ifndef _OMAP4_ISS_REGS_H_ 11 - #define _OMAP4_ISS_REGS_H_ 12 - 13 - /* ISS */ 14 - #define ISS_HL_REVISION 0x0 15 - 16 - #define ISS_HL_SYSCONFIG 0x10 17 - #define ISS_HL_SYSCONFIG_IDLEMODE_SHIFT 2 18 - #define ISS_HL_SYSCONFIG_IDLEMODE_FORCEIDLE 0x0 19 - #define ISS_HL_SYSCONFIG_IDLEMODE_NOIDLE 0x1 20 - #define ISS_HL_SYSCONFIG_IDLEMODE_SMARTIDLE 0x2 21 - #define ISS_HL_SYSCONFIG_SOFTRESET BIT(0) 22 - 23 - #define ISS_HL_IRQSTATUS_RAW(i) (0x20 + (0x10 * (i))) 24 - #define ISS_HL_IRQSTATUS(i) (0x24 + (0x10 * (i))) 25 - #define ISS_HL_IRQENABLE_SET(i) (0x28 + (0x10 * (i))) 26 - #define ISS_HL_IRQENABLE_CLR(i) (0x2c + (0x10 * (i))) 27 - 28 - #define ISS_HL_IRQ_HS_VS BIT(17) 29 - #define ISS_HL_IRQ_SIMCOP(i) BIT(12 + (i)) 30 - #define ISS_HL_IRQ_BTE BIT(11) 31 - #define ISS_HL_IRQ_CBUFF BIT(10) 32 - #define ISS_HL_IRQ_CCP2(i) BIT((i) > 3 ? 16 : 14 + (i)) 33 - #define ISS_HL_IRQ_CSIB BIT(5) 34 - #define ISS_HL_IRQ_CSIA BIT(4) 35 - #define ISS_HL_IRQ_ISP(i) BIT(i) 36 - 37 - #define ISS_CTRL 0x80 38 - #define ISS_CTRL_CLK_DIV_MASK (3 << 4) 39 - #define ISS_CTRL_INPUT_SEL_MASK (3 << 2) 40 - #define ISS_CTRL_INPUT_SEL_CSI2A (0 << 2) 41 - #define ISS_CTRL_INPUT_SEL_CSI2B (1 << 2) 42 - #define ISS_CTRL_SYNC_DETECT_VS_RAISING (3 << 0) 43 - 44 - #define ISS_CLKCTRL 0x84 45 - #define ISS_CLKCTRL_VPORT2_CLK BIT(30) 46 - #define ISS_CLKCTRL_VPORT1_CLK BIT(29) 47 - #define ISS_CLKCTRL_VPORT0_CLK BIT(28) 48 - #define ISS_CLKCTRL_CCP2 BIT(4) 49 - #define ISS_CLKCTRL_CSI2_B BIT(3) 50 - #define ISS_CLKCTRL_CSI2_A BIT(2) 51 - #define ISS_CLKCTRL_ISP BIT(1) 52 - #define ISS_CLKCTRL_SIMCOP BIT(0) 53 - 54 - #define ISS_CLKSTAT 0x88 55 - #define ISS_CLKSTAT_VPORT2_CLK BIT(30) 56 - #define ISS_CLKSTAT_VPORT1_CLK BIT(29) 57 - #define ISS_CLKSTAT_VPORT0_CLK BIT(28) 58 - #define ISS_CLKSTAT_CCP2 BIT(4) 59 - #define ISS_CLKSTAT_CSI2_B BIT(3) 60 - #define ISS_CLKSTAT_CSI2_A BIT(2) 61 - #define ISS_CLKSTAT_ISP BIT(1) 62 - #define ISS_CLKSTAT_SIMCOP BIT(0) 63 - 64 - #define ISS_PM_STATUS 0x8c 65 - #define ISS_PM_STATUS_CBUFF_PM_MASK (3 << 12) 66 - #define ISS_PM_STATUS_BTE_PM_MASK (3 << 10) 67 - #define ISS_PM_STATUS_SIMCOP_PM_MASK (3 << 8) 68 - #define ISS_PM_STATUS_ISP_PM_MASK (3 << 6) 69 - #define ISS_PM_STATUS_CCP2_PM_MASK (3 << 4) 70 - #define ISS_PM_STATUS_CSI2_B_PM_MASK (3 << 2) 71 - #define ISS_PM_STATUS_CSI2_A_PM_MASK (3 << 0) 72 - 73 - #define REGISTER0 0x0 74 - #define REGISTER0_HSCLOCKCONFIG BIT(24) 75 - #define REGISTER0_THS_TERM_MASK (0xff << 8) 76 - #define REGISTER0_THS_TERM_SHIFT 8 77 - #define REGISTER0_THS_SETTLE_MASK (0xff << 0) 78 - #define REGISTER0_THS_SETTLE_SHIFT 0 79 - 80 - #define REGISTER1 0x4 81 - #define REGISTER1_RESET_DONE_CTRLCLK BIT(29) 82 - #define REGISTER1_CLOCK_MISS_DETECTOR_STATUS BIT(25) 83 - #define REGISTER1_TCLK_TERM_MASK (0x3f << 18) 84 - #define REGISTER1_TCLK_TERM_SHIFT 18 85 - #define REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT 10 86 - #define REGISTER1_CTRLCLK_DIV_FACTOR_MASK (0x3 << 8) 87 - #define REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT 8 88 - #define REGISTER1_TCLK_SETTLE_MASK (0xff << 0) 89 - #define REGISTER1_TCLK_SETTLE_SHIFT 0 90 - 91 - #define REGISTER2 0x8 92 - 93 - #define CSI2_SYSCONFIG 0x10 94 - #define CSI2_SYSCONFIG_MSTANDBY_MODE_MASK (3 << 12) 95 - #define CSI2_SYSCONFIG_MSTANDBY_MODE_FORCE (0 << 12) 96 - #define CSI2_SYSCONFIG_MSTANDBY_MODE_NO (1 << 12) 97 - #define CSI2_SYSCONFIG_MSTANDBY_MODE_SMART (2 << 12) 98 - #define CSI2_SYSCONFIG_SOFT_RESET (1 << 1) 99 - #define CSI2_SYSCONFIG_AUTO_IDLE (1 << 0) 100 - 101 - #define CSI2_SYSSTATUS 0x14 102 - #define CSI2_SYSSTATUS_RESET_DONE BIT(0) 103 - 104 - #define CSI2_IRQSTATUS 0x18 105 - #define CSI2_IRQENABLE 0x1c 106 - 107 - /* Shared bits across CSI2_IRQENABLE and IRQSTATUS */ 108 - 109 - #define CSI2_IRQ_OCP_ERR BIT(14) 110 - #define CSI2_IRQ_SHORT_PACKET BIT(13) 111 - #define CSI2_IRQ_ECC_CORRECTION BIT(12) 112 - #define CSI2_IRQ_ECC_NO_CORRECTION BIT(11) 113 - #define CSI2_IRQ_COMPLEXIO_ERR BIT(9) 114 - #define CSI2_IRQ_FIFO_OVF BIT(8) 115 - #define CSI2_IRQ_CONTEXT0 BIT(0) 116 - 117 - #define CSI2_CTRL 0x40 118 - #define CSI2_CTRL_MFLAG_LEVH_MASK (7 << 20) 119 - #define CSI2_CTRL_MFLAG_LEVH_SHIFT 20 120 - #define CSI2_CTRL_MFLAG_LEVL_MASK (7 << 17) 121 - #define CSI2_CTRL_MFLAG_LEVL_SHIFT 17 122 - #define CSI2_CTRL_BURST_SIZE_EXPAND (1 << 16) 123 - #define CSI2_CTRL_VP_CLK_EN (1 << 15) 124 - #define CSI2_CTRL_NON_POSTED_WRITE (1 << 13) 125 - #define CSI2_CTRL_VP_ONLY_EN (1 << 11) 126 - #define CSI2_CTRL_VP_OUT_CTRL_MASK (3 << 8) 127 - #define CSI2_CTRL_VP_OUT_CTRL_SHIFT 8 128 - #define CSI2_CTRL_DBG_EN (1 << 7) 129 - #define CSI2_CTRL_BURST_SIZE_MASK (3 << 5) 130 - #define CSI2_CTRL_ENDIANNESS (1 << 4) 131 - #define CSI2_CTRL_FRAME (1 << 3) 132 - #define CSI2_CTRL_ECC_EN (1 << 2) 133 - #define CSI2_CTRL_IF_EN (1 << 0) 134 - 135 - #define CSI2_DBG_H 0x44 136 - 137 - #define CSI2_COMPLEXIO_CFG 0x50 138 - #define CSI2_COMPLEXIO_CFG_RESET_CTRL (1 << 30) 139 - #define CSI2_COMPLEXIO_CFG_RESET_DONE (1 << 29) 140 - #define CSI2_COMPLEXIO_CFG_PWD_CMD_MASK (3 << 27) 141 - #define CSI2_COMPLEXIO_CFG_PWD_CMD_OFF (0 << 27) 142 - #define CSI2_COMPLEXIO_CFG_PWD_CMD_ON (1 << 27) 143 - #define CSI2_COMPLEXIO_CFG_PWD_CMD_ULP (2 << 27) 144 - #define CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK (3 << 25) 145 - #define CSI2_COMPLEXIO_CFG_PWD_STATUS_OFF (0 << 25) 146 - #define CSI2_COMPLEXIO_CFG_PWD_STATUS_ON (1 << 25) 147 - #define CSI2_COMPLEXIO_CFG_PWD_STATUS_ULP (2 << 25) 148 - #define CSI2_COMPLEXIO_CFG_PWR_AUTO (1 << 24) 149 - #define CSI2_COMPLEXIO_CFG_DATA_POL(i) (1 << (((i) * 4) + 3)) 150 - #define CSI2_COMPLEXIO_CFG_DATA_POSITION_MASK(i) (7 << ((i) * 4)) 151 - #define CSI2_COMPLEXIO_CFG_DATA_POSITION_SHIFT(i) ((i) * 4) 152 - #define CSI2_COMPLEXIO_CFG_CLOCK_POL (1 << 3) 153 - #define CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK (7 << 0) 154 - #define CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT 0 155 - 156 - #define CSI2_COMPLEXIO_IRQSTATUS 0x54 157 - 158 - #define CSI2_SHORT_PACKET 0x5c 159 - 160 - #define CSI2_COMPLEXIO_IRQENABLE 0x60 161 - 162 - /* Shared bits across CSI2_COMPLEXIO_IRQENABLE and IRQSTATUS */ 163 - #define CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT BIT(26) 164 - #define CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER BIT(25) 165 - #define CSI2_COMPLEXIO_IRQ_STATEULPM5 BIT(24) 166 - #define CSI2_COMPLEXIO_IRQ_STATEULPM4 BIT(23) 167 - #define CSI2_COMPLEXIO_IRQ_STATEULPM3 BIT(22) 168 - #define CSI2_COMPLEXIO_IRQ_STATEULPM2 BIT(21) 169 - #define CSI2_COMPLEXIO_IRQ_STATEULPM1 BIT(20) 170 - #define CSI2_COMPLEXIO_IRQ_ERRCONTROL5 BIT(19) 171 - #define CSI2_COMPLEXIO_IRQ_ERRCONTROL4 BIT(18) 172 - #define CSI2_COMPLEXIO_IRQ_ERRCONTROL3 BIT(17) 173 - #define CSI2_COMPLEXIO_IRQ_ERRCONTROL2 BIT(16) 174 - #define CSI2_COMPLEXIO_IRQ_ERRCONTROL1 BIT(15) 175 - #define CSI2_COMPLEXIO_IRQ_ERRESC5 BIT(14) 176 - #define CSI2_COMPLEXIO_IRQ_ERRESC4 BIT(13) 177 - #define CSI2_COMPLEXIO_IRQ_ERRESC3 BIT(12) 178 - #define CSI2_COMPLEXIO_IRQ_ERRESC2 BIT(11) 179 - #define CSI2_COMPLEXIO_IRQ_ERRESC1 BIT(10) 180 - #define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 BIT(9) 181 - #define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 BIT(8) 182 - #define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 BIT(7) 183 - #define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 BIT(6) 184 - #define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 BIT(5) 185 - #define CSI2_COMPLEXIO_IRQ_ERRSOTHS5 BIT(4) 186 - #define CSI2_COMPLEXIO_IRQ_ERRSOTHS4 BIT(3) 187 - #define CSI2_COMPLEXIO_IRQ_ERRSOTHS3 BIT(2) 188 - #define CSI2_COMPLEXIO_IRQ_ERRSOTHS2 BIT(1) 189 - #define CSI2_COMPLEXIO_IRQ_ERRSOTHS1 BIT(0) 190 - 191 - #define CSI2_DBG_P 0x68 192 - 193 - #define CSI2_TIMING 0x6c 194 - #define CSI2_TIMING_FORCE_RX_MODE_IO1 BIT(15) 195 - #define CSI2_TIMING_STOP_STATE_X16_IO1 BIT(14) 196 - #define CSI2_TIMING_STOP_STATE_X4_IO1 BIT(13) 197 - #define CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK (0x1fff << 0) 198 - #define CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT 0 199 - 200 - #define CSI2_CTX_CTRL1(i) (0x70 + (0x20 * (i))) 201 - #define CSI2_CTX_CTRL1_GENERIC BIT(30) 202 - #define CSI2_CTX_CTRL1_TRANSCODE (0xf << 24) 203 - #define CSI2_CTX_CTRL1_FEC_NUMBER_MASK (0xff << 16) 204 - #define CSI2_CTX_CTRL1_COUNT_MASK (0xff << 8) 205 - #define CSI2_CTX_CTRL1_COUNT_SHIFT 8 206 - #define CSI2_CTX_CTRL1_EOF_EN BIT(7) 207 - #define CSI2_CTX_CTRL1_EOL_EN BIT(6) 208 - #define CSI2_CTX_CTRL1_CS_EN BIT(5) 209 - #define CSI2_CTX_CTRL1_COUNT_UNLOCK BIT(4) 210 - #define CSI2_CTX_CTRL1_PING_PONG BIT(3) 211 - #define CSI2_CTX_CTRL1_CTX_EN BIT(0) 212 - 213 - #define CSI2_CTX_CTRL2(i) (0x74 + (0x20 * (i))) 214 - #define CSI2_CTX_CTRL2_FRAME_MASK (0xffff << 16) 215 - #define CSI2_CTX_CTRL2_FRAME_SHIFT 16 216 - #define CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT 13 217 - #define CSI2_CTX_CTRL2_USER_DEF_MAP_MASK \ 218 - (0x3 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT) 219 - #define CSI2_CTX_CTRL2_VIRTUAL_ID_MASK (3 << 11) 220 - #define CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT 11 221 - #define CSI2_CTX_CTRL2_DPCM_PRED (1 << 10) 222 - #define CSI2_CTX_CTRL2_FORMAT_MASK (0x3ff << 0) 223 - #define CSI2_CTX_CTRL2_FORMAT_SHIFT 0 224 - 225 - #define CSI2_CTX_DAT_OFST(i) (0x78 + (0x20 * (i))) 226 - #define CSI2_CTX_DAT_OFST_MASK (0xfff << 5) 227 - 228 - #define CSI2_CTX_PING_ADDR(i) (0x7c + (0x20 * (i))) 229 - #define CSI2_CTX_PING_ADDR_MASK 0xffffffe0 230 - 231 - #define CSI2_CTX_PONG_ADDR(i) (0x80 + (0x20 * (i))) 232 - #define CSI2_CTX_PONG_ADDR_MASK CSI2_CTX_PING_ADDR_MASK 233 - 234 - #define CSI2_CTX_IRQENABLE(i) (0x84 + (0x20 * (i))) 235 - #define CSI2_CTX_IRQSTATUS(i) (0x88 + (0x20 * (i))) 236 - 237 - #define CSI2_CTX_CTRL3(i) (0x8c + (0x20 * (i))) 238 - #define CSI2_CTX_CTRL3_ALPHA_SHIFT 5 239 - #define CSI2_CTX_CTRL3_ALPHA_MASK \ 240 - (0x3fff << CSI2_CTX_CTRL3_ALPHA_SHIFT) 241 - 242 - /* Shared bits across CSI2_CTX_IRQENABLE and IRQSTATUS */ 243 - #define CSI2_CTX_IRQ_ECC_CORRECTION BIT(8) 244 - #define CSI2_CTX_IRQ_LINE_NUMBER BIT(7) 245 - #define CSI2_CTX_IRQ_FRAME_NUMBER BIT(6) 246 - #define CSI2_CTX_IRQ_CS BIT(5) 247 - #define CSI2_CTX_IRQ_LE BIT(3) 248 - #define CSI2_CTX_IRQ_LS BIT(2) 249 - #define CSI2_CTX_IRQ_FE BIT(1) 250 - #define CSI2_CTX_IRQ_FS BIT(0) 251 - 252 - /* ISS BTE */ 253 - #define BTE_CTRL (0x0030) 254 - #define BTE_CTRL_BW_LIMITER_MASK (0x3ff << 22) 255 - #define BTE_CTRL_BW_LIMITER_SHIFT 22 256 - 257 - /* ISS ISP_SYS1 */ 258 - #define ISP5_REVISION (0x0000) 259 - #define ISP5_SYSCONFIG (0x0010) 260 - #define ISP5_SYSCONFIG_STANDBYMODE_MASK (3 << 4) 261 - #define ISP5_SYSCONFIG_STANDBYMODE_FORCE (0 << 4) 262 - #define ISP5_SYSCONFIG_STANDBYMODE_NO (1 << 4) 263 - #define ISP5_SYSCONFIG_STANDBYMODE_SMART (2 << 4) 264 - #define ISP5_SYSCONFIG_SOFTRESET (1 << 1) 265 - 266 - #define ISP5_IRQSTATUS(i) (0x0028 + (0x10 * (i))) 267 - #define ISP5_IRQENABLE_SET(i) (0x002c + (0x10 * (i))) 268 - #define ISP5_IRQENABLE_CLR(i) (0x0030 + (0x10 * (i))) 269 - 270 - /* Bits shared for ISP5_IRQ* registers */ 271 - #define ISP5_IRQ_OCP_ERR BIT(31) 272 - #define ISP5_IRQ_IPIPE_INT_DPC_RNEW1 BIT(29) 273 - #define ISP5_IRQ_IPIPE_INT_DPC_RNEW0 BIT(28) 274 - #define ISP5_IRQ_IPIPE_INT_DPC_INIT BIT(27) 275 - #define ISP5_IRQ_IPIPE_INT_EOF BIT(25) 276 - #define ISP5_IRQ_H3A_INT_EOF BIT(24) 277 - #define ISP5_IRQ_RSZ_INT_EOF1 BIT(23) 278 - #define ISP5_IRQ_RSZ_INT_EOF0 BIT(22) 279 - #define ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR BIT(19) 280 - #define ISP5_IRQ_RSZ_FIFO_OVF BIT(18) 281 - #define ISP5_IRQ_RSZ_INT_CYC_RSZB BIT(17) 282 - #define ISP5_IRQ_RSZ_INT_CYC_RSZA BIT(16) 283 - #define ISP5_IRQ_RSZ_INT_DMA BIT(15) 284 - #define ISP5_IRQ_RSZ_INT_LAST_PIX BIT(14) 285 - #define ISP5_IRQ_RSZ_INT_REG BIT(13) 286 - #define ISP5_IRQ_H3A_INT BIT(12) 287 - #define ISP5_IRQ_AF_INT BIT(11) 288 - #define ISP5_IRQ_AEW_INT BIT(10) 289 - #define ISP5_IRQ_IPIPEIF_IRQ BIT(9) 290 - #define ISP5_IRQ_IPIPE_INT_HST BIT(8) 291 - #define ISP5_IRQ_IPIPE_INT_BSC BIT(7) 292 - #define ISP5_IRQ_IPIPE_INT_DMA BIT(6) 293 - #define ISP5_IRQ_IPIPE_INT_LAST_PIX BIT(5) 294 - #define ISP5_IRQ_IPIPE_INT_REG BIT(4) 295 - #define ISP5_IRQ_ISIF_INT(i) BIT(i) 296 - 297 - #define ISP5_CTRL (0x006c) 298 - #define ISP5_CTRL_MSTANDBY BIT(24) 299 - #define ISP5_CTRL_VD_PULSE_EXT BIT(23) 300 - #define ISP5_CTRL_MSTANDBY_WAIT BIT(20) 301 - #define ISP5_CTRL_BL_CLK_ENABLE BIT(15) 302 - #define ISP5_CTRL_ISIF_CLK_ENABLE BIT(14) 303 - #define ISP5_CTRL_H3A_CLK_ENABLE BIT(13) 304 - #define ISP5_CTRL_RSZ_CLK_ENABLE BIT(12) 305 - #define ISP5_CTRL_IPIPE_CLK_ENABLE BIT(11) 306 - #define ISP5_CTRL_IPIPEIF_CLK_ENABLE BIT(10) 307 - #define ISP5_CTRL_SYNC_ENABLE BIT(9) 308 - #define ISP5_CTRL_PSYNC_CLK_SEL BIT(8) 309 - 310 - /* ISS ISP ISIF register offsets */ 311 - #define ISIF_SYNCEN (0x0000) 312 - #define ISIF_SYNCEN_DWEN BIT(1) 313 - #define ISIF_SYNCEN_SYEN BIT(0) 314 - 315 - #define ISIF_MODESET (0x0004) 316 - #define ISIF_MODESET_INPMOD_MASK (3 << 12) 317 - #define ISIF_MODESET_INPMOD_RAW (0 << 12) 318 - #define ISIF_MODESET_INPMOD_YCBCR16 (1 << 12) 319 - #define ISIF_MODESET_INPMOD_YCBCR8 (2 << 12) 320 - #define ISIF_MODESET_CCDW_MASK (7 << 8) 321 - #define ISIF_MODESET_CCDW_2BIT (2 << 8) 322 - #define ISIF_MODESET_CCDMD (1 << 7) 323 - #define ISIF_MODESET_SWEN (1 << 5) 324 - #define ISIF_MODESET_HDPOL (1 << 3) 325 - #define ISIF_MODESET_VDPOL (1 << 2) 326 - 327 - #define ISIF_SPH (0x0018) 328 - #define ISIF_SPH_MASK (0x7fff) 329 - 330 - #define ISIF_LNH (0x001c) 331 - #define ISIF_LNH_MASK (0x7fff) 332 - 333 - #define ISIF_LNV (0x0028) 334 - #define ISIF_LNV_MASK (0x7fff) 335 - 336 - #define ISIF_HSIZE (0x0034) 337 - #define ISIF_HSIZE_ADCR BIT(12) 338 - #define ISIF_HSIZE_HSIZE_MASK (0xfff) 339 - 340 - #define ISIF_CADU (0x003c) 341 - #define ISIF_CADU_MASK (0x7ff) 342 - 343 - #define ISIF_CADL (0x0040) 344 - #define ISIF_CADL_MASK (0xffff) 345 - 346 - #define ISIF_CCOLP (0x004c) 347 - #define ISIF_CCOLP_CP0_F0_R (0 << 6) 348 - #define ISIF_CCOLP_CP0_F0_GR (1 << 6) 349 - #define ISIF_CCOLP_CP0_F0_B (3 << 6) 350 - #define ISIF_CCOLP_CP0_F0_GB (2 << 6) 351 - #define ISIF_CCOLP_CP1_F0_R (0 << 4) 352 - #define ISIF_CCOLP_CP1_F0_GR (1 << 4) 353 - #define ISIF_CCOLP_CP1_F0_B (3 << 4) 354 - #define ISIF_CCOLP_CP1_F0_GB (2 << 4) 355 - #define ISIF_CCOLP_CP2_F0_R (0 << 2) 356 - #define ISIF_CCOLP_CP2_F0_GR (1 << 2) 357 - #define ISIF_CCOLP_CP2_F0_B (3 << 2) 358 - #define ISIF_CCOLP_CP2_F0_GB (2 << 2) 359 - #define ISIF_CCOLP_CP3_F0_R (0 << 0) 360 - #define ISIF_CCOLP_CP3_F0_GR (1 << 0) 361 - #define ISIF_CCOLP_CP3_F0_B (3 << 0) 362 - #define ISIF_CCOLP_CP3_F0_GB (2 << 0) 363 - 364 - #define ISIF_VDINT(i) (0x0070 + (i) * 4) 365 - #define ISIF_VDINT_MASK (0x7fff) 366 - 367 - #define ISIF_CGAMMAWD (0x0080) 368 - #define ISIF_CGAMMAWD_GWDI_MASK (0xf << 1) 369 - #define ISIF_CGAMMAWD_GWDI(bpp) ((16 - (bpp)) << 1) 370 - 371 - #define ISIF_CCDCFG (0x0088) 372 - #define ISIF_CCDCFG_Y8POS BIT(11) 373 - 374 - /* ISS ISP IPIPEIF register offsets */ 375 - #define IPIPEIF_ENABLE (0x0000) 376 - 377 - #define IPIPEIF_CFG1 (0x0004) 378 - #define IPIPEIF_CFG1_INPSRC1_MASK (3 << 14) 379 - #define IPIPEIF_CFG1_INPSRC1_VPORT_RAW (0 << 14) 380 - #define IPIPEIF_CFG1_INPSRC1_SDRAM_RAW (1 << 14) 381 - #define IPIPEIF_CFG1_INPSRC1_ISIF_DARKFM (2 << 14) 382 - #define IPIPEIF_CFG1_INPSRC1_SDRAM_YUV (3 << 14) 383 - #define IPIPEIF_CFG1_INPSRC2_MASK (3 << 2) 384 - #define IPIPEIF_CFG1_INPSRC2_ISIF (0 << 2) 385 - #define IPIPEIF_CFG1_INPSRC2_SDRAM_RAW (1 << 2) 386 - #define IPIPEIF_CFG1_INPSRC2_ISIF_DARKFM (2 << 2) 387 - #define IPIPEIF_CFG1_INPSRC2_SDRAM_YUV (3 << 2) 388 - 389 - #define IPIPEIF_CFG2 (0x0030) 390 - #define IPIPEIF_CFG2_YUV8P BIT(7) 391 - #define IPIPEIF_CFG2_YUV8 BIT(6) 392 - #define IPIPEIF_CFG2_YUV16 BIT(3) 393 - #define IPIPEIF_CFG2_VDPOL BIT(2) 394 - #define IPIPEIF_CFG2_HDPOL BIT(1) 395 - #define IPIPEIF_CFG2_INTSW BIT(0) 396 - 397 - #define IPIPEIF_CLKDIV (0x0040) 398 - 399 - /* ISS ISP IPIPE register offsets */ 400 - #define IPIPE_SRC_EN (0x0000) 401 - #define IPIPE_SRC_EN_EN BIT(0) 402 - 403 - #define IPIPE_SRC_MODE (0x0004) 404 - #define IPIPE_SRC_MODE_WRT BIT(1) 405 - #define IPIPE_SRC_MODE_OST BIT(0) 406 - 407 - #define IPIPE_SRC_FMT (0x0008) 408 - #define IPIPE_SRC_FMT_RAW2YUV (0 << 0) 409 - #define IPIPE_SRC_FMT_RAW2RAW (1 << 0) 410 - #define IPIPE_SRC_FMT_RAW2STATS (2 << 0) 411 - #define IPIPE_SRC_FMT_YUV2YUV (3 << 0) 412 - 413 - #define IPIPE_SRC_COL (0x000c) 414 - #define IPIPE_SRC_COL_OO_R (0 << 6) 415 - #define IPIPE_SRC_COL_OO_GR (1 << 6) 416 - #define IPIPE_SRC_COL_OO_B (3 << 6) 417 - #define IPIPE_SRC_COL_OO_GB (2 << 6) 418 - #define IPIPE_SRC_COL_OE_R (0 << 4) 419 - #define IPIPE_SRC_COL_OE_GR (1 << 4) 420 - #define IPIPE_SRC_COL_OE_B (3 << 4) 421 - #define IPIPE_SRC_COL_OE_GB (2 << 4) 422 - #define IPIPE_SRC_COL_EO_R (0 << 2) 423 - #define IPIPE_SRC_COL_EO_GR (1 << 2) 424 - #define IPIPE_SRC_COL_EO_B (3 << 2) 425 - #define IPIPE_SRC_COL_EO_GB (2 << 2) 426 - #define IPIPE_SRC_COL_EE_R (0 << 0) 427 - #define IPIPE_SRC_COL_EE_GR (1 << 0) 428 - #define IPIPE_SRC_COL_EE_B (3 << 0) 429 - #define IPIPE_SRC_COL_EE_GB (2 << 0) 430 - 431 - #define IPIPE_SRC_VPS (0x0010) 432 - #define IPIPE_SRC_VPS_MASK (0xffff) 433 - 434 - #define IPIPE_SRC_VSZ (0x0014) 435 - #define IPIPE_SRC_VSZ_MASK (0x1fff) 436 - 437 - #define IPIPE_SRC_HPS (0x0018) 438 - #define IPIPE_SRC_HPS_MASK (0xffff) 439 - 440 - #define IPIPE_SRC_HSZ (0x001c) 441 - #define IPIPE_SRC_HSZ_MASK (0x1ffe) 442 - 443 - #define IPIPE_SEL_SBU (0x0020) 444 - 445 - #define IPIPE_SRC_STA (0x0024) 446 - 447 - #define IPIPE_GCK_MMR (0x0028) 448 - #define IPIPE_GCK_MMR_REG BIT(0) 449 - 450 - #define IPIPE_GCK_PIX (0x002c) 451 - #define IPIPE_GCK_PIX_G3 BIT(3) 452 - #define IPIPE_GCK_PIX_G2 BIT(2) 453 - #define IPIPE_GCK_PIX_G1 BIT(1) 454 - #define IPIPE_GCK_PIX_G0 BIT(0) 455 - 456 - #define IPIPE_DPC_LUT_EN (0x0034) 457 - #define IPIPE_DPC_LUT_SEL (0x0038) 458 - #define IPIPE_DPC_LUT_ADR (0x003c) 459 - #define IPIPE_DPC_LUT_SIZ (0x0040) 460 - 461 - #define IPIPE_DPC_OTF_EN (0x0044) 462 - #define IPIPE_DPC_OTF_TYP (0x0048) 463 - #define IPIPE_DPC_OTF_2_D_THR_R (0x004c) 464 - #define IPIPE_DPC_OTF_2_D_THR_GR (0x0050) 465 - #define IPIPE_DPC_OTF_2_D_THR_GB (0x0054) 466 - #define IPIPE_DPC_OTF_2_D_THR_B (0x0058) 467 - #define IPIPE_DPC_OTF_2_C_THR_R (0x005c) 468 - #define IPIPE_DPC_OTF_2_C_THR_GR (0x0060) 469 - #define IPIPE_DPC_OTF_2_C_THR_GB (0x0064) 470 - #define IPIPE_DPC_OTF_2_C_THR_B (0x0068) 471 - #define IPIPE_DPC_OTF_3_SHF (0x006c) 472 - #define IPIPE_DPC_OTF_3_D_THR (0x0070) 473 - #define IPIPE_DPC_OTF_3_D_SPL (0x0074) 474 - #define IPIPE_DPC_OTF_3_D_MIN (0x0078) 475 - #define IPIPE_DPC_OTF_3_D_MAX (0x007c) 476 - #define IPIPE_DPC_OTF_3_C_THR (0x0080) 477 - #define IPIPE_DPC_OTF_3_C_SLP (0x0084) 478 - #define IPIPE_DPC_OTF_3_C_MIN (0x0088) 479 - #define IPIPE_DPC_OTF_3_C_MAX (0x008c) 480 - 481 - #define IPIPE_LSC_VOFT (0x0090) 482 - #define IPIPE_LSC_VA2 (0x0094) 483 - #define IPIPE_LSC_VA1 (0x0098) 484 - #define IPIPE_LSC_VS (0x009c) 485 - #define IPIPE_LSC_HOFT (0x00a0) 486 - #define IPIPE_LSC_HA2 (0x00a4) 487 - #define IPIPE_LSC_HA1 (0x00a8) 488 - #define IPIPE_LSC_HS (0x00ac) 489 - #define IPIPE_LSC_GAN_R (0x00b0) 490 - #define IPIPE_LSC_GAN_GR (0x00b4) 491 - #define IPIPE_LSC_GAN_GB (0x00b8) 492 - #define IPIPE_LSC_GAN_B (0x00bc) 493 - #define IPIPE_LSC_OFT_R (0x00c0) 494 - #define IPIPE_LSC_OFT_GR (0x00c4) 495 - #define IPIPE_LSC_OFT_GB (0x00c8) 496 - #define IPIPE_LSC_OFT_B (0x00cc) 497 - #define IPIPE_LSC_SHF (0x00d0) 498 - #define IPIPE_LSC_MAX (0x00d4) 499 - 500 - #define IPIPE_D2F_1ST_EN (0x00d8) 501 - #define IPIPE_D2F_1ST_TYP (0x00dc) 502 - #define IPIPE_D2F_1ST_THR_00 (0x00e0) 503 - #define IPIPE_D2F_1ST_THR_01 (0x00e4) 504 - #define IPIPE_D2F_1ST_THR_02 (0x00e8) 505 - #define IPIPE_D2F_1ST_THR_03 (0x00ec) 506 - #define IPIPE_D2F_1ST_THR_04 (0x00f0) 507 - #define IPIPE_D2F_1ST_THR_05 (0x00f4) 508 - #define IPIPE_D2F_1ST_THR_06 (0x00f8) 509 - #define IPIPE_D2F_1ST_THR_07 (0x00fc) 510 - #define IPIPE_D2F_1ST_STR_00 (0x0100) 511 - #define IPIPE_D2F_1ST_STR_01 (0x0104) 512 - #define IPIPE_D2F_1ST_STR_02 (0x0108) 513 - #define IPIPE_D2F_1ST_STR_03 (0x010c) 514 - #define IPIPE_D2F_1ST_STR_04 (0x0110) 515 - #define IPIPE_D2F_1ST_STR_05 (0x0114) 516 - #define IPIPE_D2F_1ST_STR_06 (0x0118) 517 - #define IPIPE_D2F_1ST_STR_07 (0x011c) 518 - #define IPIPE_D2F_1ST_SPR_00 (0x0120) 519 - #define IPIPE_D2F_1ST_SPR_01 (0x0124) 520 - #define IPIPE_D2F_1ST_SPR_02 (0x0128) 521 - #define IPIPE_D2F_1ST_SPR_03 (0x012c) 522 - #define IPIPE_D2F_1ST_SPR_04 (0x0130) 523 - #define IPIPE_D2F_1ST_SPR_05 (0x0134) 524 - #define IPIPE_D2F_1ST_SPR_06 (0x0138) 525 - #define IPIPE_D2F_1ST_SPR_07 (0x013c) 526 - #define IPIPE_D2F_1ST_EDG_MIN (0x0140) 527 - #define IPIPE_D2F_1ST_EDG_MAX (0x0144) 528 - #define IPIPE_D2F_2ND_EN (0x0148) 529 - #define IPIPE_D2F_2ND_TYP (0x014c) 530 - #define IPIPE_D2F_2ND_THR00 (0x0150) 531 - #define IPIPE_D2F_2ND_THR01 (0x0154) 532 - #define IPIPE_D2F_2ND_THR02 (0x0158) 533 - #define IPIPE_D2F_2ND_THR03 (0x015c) 534 - #define IPIPE_D2F_2ND_THR04 (0x0160) 535 - #define IPIPE_D2F_2ND_THR05 (0x0164) 536 - #define IPIPE_D2F_2ND_THR06 (0x0168) 537 - #define IPIPE_D2F_2ND_THR07 (0x016c) 538 - #define IPIPE_D2F_2ND_STR_00 (0x0170) 539 - #define IPIPE_D2F_2ND_STR_01 (0x0174) 540 - #define IPIPE_D2F_2ND_STR_02 (0x0178) 541 - #define IPIPE_D2F_2ND_STR_03 (0x017c) 542 - #define IPIPE_D2F_2ND_STR_04 (0x0180) 543 - #define IPIPE_D2F_2ND_STR_05 (0x0184) 544 - #define IPIPE_D2F_2ND_STR_06 (0x0188) 545 - #define IPIPE_D2F_2ND_STR_07 (0x018c) 546 - #define IPIPE_D2F_2ND_SPR_00 (0x0190) 547 - #define IPIPE_D2F_2ND_SPR_01 (0x0194) 548 - #define IPIPE_D2F_2ND_SPR_02 (0x0198) 549 - #define IPIPE_D2F_2ND_SPR_03 (0x019c) 550 - #define IPIPE_D2F_2ND_SPR_04 (0x01a0) 551 - #define IPIPE_D2F_2ND_SPR_05 (0x01a4) 552 - #define IPIPE_D2F_2ND_SPR_06 (0x01a8) 553 - #define IPIPE_D2F_2ND_SPR_07 (0x01ac) 554 - #define IPIPE_D2F_2ND_EDG_MIN (0x01b0) 555 - #define IPIPE_D2F_2ND_EDG_MAX (0x01b4) 556 - 557 - #define IPIPE_GIC_EN (0x01b8) 558 - #define IPIPE_GIC_TYP (0x01bc) 559 - #define IPIPE_GIC_GAN (0x01c0) 560 - #define IPIPE_GIC_NFGAIN (0x01c4) 561 - #define IPIPE_GIC_THR (0x01c8) 562 - #define IPIPE_GIC_SLP (0x01cc) 563 - 564 - #define IPIPE_WB2_OFT_R (0x01d0) 565 - #define IPIPE_WB2_OFT_GR (0x01d4) 566 - #define IPIPE_WB2_OFT_GB (0x01d8) 567 - #define IPIPE_WB2_OFT_B (0x01dc) 568 - 569 - #define IPIPE_WB2_WGN_R (0x01e0) 570 - #define IPIPE_WB2_WGN_GR (0x01e4) 571 - #define IPIPE_WB2_WGN_GB (0x01e8) 572 - #define IPIPE_WB2_WGN_B (0x01ec) 573 - 574 - #define IPIPE_CFA_MODE (0x01f0) 575 - #define IPIPE_CFA_2DIR_HPF_THR (0x01f4) 576 - #define IPIPE_CFA_2DIR_HPF_SLP (0x01f8) 577 - #define IPIPE_CFA_2DIR_MIX_THR (0x01fc) 578 - #define IPIPE_CFA_2DIR_MIX_SLP (0x0200) 579 - #define IPIPE_CFA_2DIR_DIR_TRH (0x0204) 580 - #define IPIPE_CFA_2DIR_DIR_SLP (0x0208) 581 - #define IPIPE_CFA_2DIR_NDWT (0x020c) 582 - #define IPIPE_CFA_MONO_HUE_FRA (0x0210) 583 - #define IPIPE_CFA_MONO_EDG_THR (0x0214) 584 - #define IPIPE_CFA_MONO_THR_MIN (0x0218) 585 - 586 - #define IPIPE_CFA_MONO_THR_SLP (0x021c) 587 - #define IPIPE_CFA_MONO_SLP_MIN (0x0220) 588 - #define IPIPE_CFA_MONO_SLP_SLP (0x0224) 589 - #define IPIPE_CFA_MONO_LPWT (0x0228) 590 - 591 - #define IPIPE_RGB1_MUL_RR (0x022c) 592 - #define IPIPE_RGB1_MUL_GR (0x0230) 593 - #define IPIPE_RGB1_MUL_BR (0x0234) 594 - #define IPIPE_RGB1_MUL_RG (0x0238) 595 - #define IPIPE_RGB1_MUL_GG (0x023c) 596 - #define IPIPE_RGB1_MUL_BG (0x0240) 597 - #define IPIPE_RGB1_MUL_RB (0x0244) 598 - #define IPIPE_RGB1_MUL_GB (0x0248) 599 - #define IPIPE_RGB1_MUL_BB (0x024c) 600 - #define IPIPE_RGB1_OFT_OR (0x0250) 601 - #define IPIPE_RGB1_OFT_OG (0x0254) 602 - #define IPIPE_RGB1_OFT_OB (0x0258) 603 - #define IPIPE_GMM_CFG (0x025c) 604 - #define IPIPE_RGB2_MUL_RR (0x0260) 605 - #define IPIPE_RGB2_MUL_GR (0x0264) 606 - #define IPIPE_RGB2_MUL_BR (0x0268) 607 - #define IPIPE_RGB2_MUL_RG (0x026c) 608 - #define IPIPE_RGB2_MUL_GG (0x0270) 609 - #define IPIPE_RGB2_MUL_BG (0x0274) 610 - #define IPIPE_RGB2_MUL_RB (0x0278) 611 - #define IPIPE_RGB2_MUL_GB (0x027c) 612 - #define IPIPE_RGB2_MUL_BB (0x0280) 613 - #define IPIPE_RGB2_OFT_OR (0x0284) 614 - #define IPIPE_RGB2_OFT_OG (0x0288) 615 - #define IPIPE_RGB2_OFT_OB (0x028c) 616 - 617 - #define IPIPE_YUV_ADJ (0x0294) 618 - #define IPIPE_YUV_MUL_RY (0x0298) 619 - #define IPIPE_YUV_MUL_GY (0x029c) 620 - #define IPIPE_YUV_MUL_BY (0x02a0) 621 - #define IPIPE_YUV_MUL_RCB (0x02a4) 622 - #define IPIPE_YUV_MUL_GCB (0x02a8) 623 - #define IPIPE_YUV_MUL_BCB (0x02ac) 624 - #define IPIPE_YUV_MUL_RCR (0x02b0) 625 - #define IPIPE_YUV_MUL_GCR (0x02b4) 626 - #define IPIPE_YUV_MUL_BCR (0x02b8) 627 - #define IPIPE_YUV_OFT_Y (0x02bc) 628 - #define IPIPE_YUV_OFT_CB (0x02c0) 629 - #define IPIPE_YUV_OFT_CR (0x02c4) 630 - 631 - #define IPIPE_YUV_PHS (0x02c8) 632 - #define IPIPE_YUV_PHS_LPF BIT(1) 633 - #define IPIPE_YUV_PHS_POS BIT(0) 634 - 635 - #define IPIPE_YEE_EN (0x02d4) 636 - #define IPIPE_YEE_TYP (0x02d8) 637 - #define IPIPE_YEE_SHF (0x02dc) 638 - #define IPIPE_YEE_MUL_00 (0x02e0) 639 - #define IPIPE_YEE_MUL_01 (0x02e4) 640 - #define IPIPE_YEE_MUL_02 (0x02e8) 641 - #define IPIPE_YEE_MUL_10 (0x02ec) 642 - #define IPIPE_YEE_MUL_11 (0x02f0) 643 - #define IPIPE_YEE_MUL_12 (0x02f4) 644 - #define IPIPE_YEE_MUL_20 (0x02f8) 645 - #define IPIPE_YEE_MUL_21 (0x02fc) 646 - #define IPIPE_YEE_MUL_22 (0x0300) 647 - #define IPIPE_YEE_THR (0x0304) 648 - #define IPIPE_YEE_E_GAN (0x0308) 649 - #define IPIPE_YEE_E_THR_1 (0x030c) 650 - #define IPIPE_YEE_E_THR_2 (0x0310) 651 - #define IPIPE_YEE_G_GAN (0x0314) 652 - #define IPIPE_YEE_G_OFT (0x0318) 653 - 654 - #define IPIPE_CAR_EN (0x031c) 655 - #define IPIPE_CAR_TYP (0x0320) 656 - #define IPIPE_CAR_SW (0x0324) 657 - #define IPIPE_CAR_HPF_TYP (0x0328) 658 - #define IPIPE_CAR_HPF_SHF (0x032c) 659 - #define IPIPE_CAR_HPF_THR (0x0330) 660 - #define IPIPE_CAR_GN1_GAN (0x0334) 661 - #define IPIPE_CAR_GN1_SHF (0x0338) 662 - #define IPIPE_CAR_GN1_MIN (0x033c) 663 - #define IPIPE_CAR_GN2_GAN (0x0340) 664 - #define IPIPE_CAR_GN2_SHF (0x0344) 665 - #define IPIPE_CAR_GN2_MIN (0x0348) 666 - #define IPIPE_CGS_EN (0x034c) 667 - #define IPIPE_CGS_GN1_L_THR (0x0350) 668 - #define IPIPE_CGS_GN1_L_GAIN (0x0354) 669 - #define IPIPE_CGS_GN1_L_SHF (0x0358) 670 - #define IPIPE_CGS_GN1_L_MIN (0x035c) 671 - #define IPIPE_CGS_GN1_H_THR (0x0360) 672 - #define IPIPE_CGS_GN1_H_GAIN (0x0364) 673 - #define IPIPE_CGS_GN1_H_SHF (0x0368) 674 - #define IPIPE_CGS_GN1_H_MIN (0x036c) 675 - #define IPIPE_CGS_GN2_L_THR (0x0370) 676 - #define IPIPE_CGS_GN2_L_GAIN (0x0374) 677 - #define IPIPE_CGS_GN2_L_SHF (0x0378) 678 - #define IPIPE_CGS_GN2_L_MIN (0x037c) 679 - 680 - #define IPIPE_BOX_EN (0x0380) 681 - #define IPIPE_BOX_MODE (0x0384) 682 - #define IPIPE_BOX_TYP (0x0388) 683 - #define IPIPE_BOX_SHF (0x038c) 684 - #define IPIPE_BOX_SDR_SAD_H (0x0390) 685 - #define IPIPE_BOX_SDR_SAD_L (0x0394) 686 - 687 - #define IPIPE_HST_EN (0x039c) 688 - #define IPIPE_HST_MODE (0x03a0) 689 - #define IPIPE_HST_SEL (0x03a4) 690 - #define IPIPE_HST_PARA (0x03a8) 691 - #define IPIPE_HST_0_VPS (0x03ac) 692 - #define IPIPE_HST_0_VSZ (0x03b0) 693 - #define IPIPE_HST_0_HPS (0x03b4) 694 - #define IPIPE_HST_0_HSZ (0x03b8) 695 - #define IPIPE_HST_1_VPS (0x03bc) 696 - #define IPIPE_HST_1_VSZ (0x03c0) 697 - #define IPIPE_HST_1_HPS (0x03c4) 698 - #define IPIPE_HST_1_HSZ (0x03c8) 699 - #define IPIPE_HST_2_VPS (0x03cc) 700 - #define IPIPE_HST_2_VSZ (0x03d0) 701 - #define IPIPE_HST_2_HPS (0x03d4) 702 - #define IPIPE_HST_2_HSZ (0x03d8) 703 - #define IPIPE_HST_3_VPS (0x03dc) 704 - #define IPIPE_HST_3_VSZ (0x03e0) 705 - #define IPIPE_HST_3_HPS (0x03e4) 706 - #define IPIPE_HST_3_HSZ (0x03e8) 707 - #define IPIPE_HST_TBL (0x03ec) 708 - #define IPIPE_HST_MUL_R (0x03f0) 709 - #define IPIPE_HST_MUL_GR (0x03f4) 710 - #define IPIPE_HST_MUL_GB (0x03f8) 711 - #define IPIPE_HST_MUL_B (0x03fc) 712 - 713 - #define IPIPE_BSC_EN (0x0400) 714 - #define IPIPE_BSC_MODE (0x0404) 715 - #define IPIPE_BSC_TYP (0x0408) 716 - #define IPIPE_BSC_ROW_VCT (0x040c) 717 - #define IPIPE_BSC_ROW_SHF (0x0410) 718 - #define IPIPE_BSC_ROW_VPO (0x0414) 719 - #define IPIPE_BSC_ROW_VNU (0x0418) 720 - #define IPIPE_BSC_ROW_VSKIP (0x041c) 721 - #define IPIPE_BSC_ROW_HPO (0x0420) 722 - #define IPIPE_BSC_ROW_HNU (0x0424) 723 - #define IPIPE_BSC_ROW_HSKIP (0x0428) 724 - #define IPIPE_BSC_COL_VCT (0x042c) 725 - #define IPIPE_BSC_COL_SHF (0x0430) 726 - #define IPIPE_BSC_COL_VPO (0x0434) 727 - #define IPIPE_BSC_COL_VNU (0x0438) 728 - #define IPIPE_BSC_COL_VSKIP (0x043c) 729 - #define IPIPE_BSC_COL_HPO (0x0440) 730 - #define IPIPE_BSC_COL_HNU (0x0444) 731 - #define IPIPE_BSC_COL_HSKIP (0x0448) 732 - 733 - #define IPIPE_BSC_EN (0x0400) 734 - 735 - /* ISS ISP Resizer register offsets */ 736 - #define RSZ_REVISION (0x0000) 737 - #define RSZ_SYSCONFIG (0x0004) 738 - #define RSZ_SYSCONFIG_RSZB_CLK_EN BIT(9) 739 - #define RSZ_SYSCONFIG_RSZA_CLK_EN BIT(8) 740 - 741 - #define RSZ_IN_FIFO_CTRL (0x000c) 742 - #define RSZ_IN_FIFO_CTRL_THRLD_LOW_MASK (0x1ff << 16) 743 - #define RSZ_IN_FIFO_CTRL_THRLD_LOW_SHIFT 16 744 - #define RSZ_IN_FIFO_CTRL_THRLD_HIGH_MASK (0x1ff << 0) 745 - #define RSZ_IN_FIFO_CTRL_THRLD_HIGH_SHIFT 0 746 - 747 - #define RSZ_FRACDIV (0x0008) 748 - #define RSZ_FRACDIV_MASK (0xffff) 749 - 750 - #define RSZ_SRC_EN (0x0020) 751 - #define RSZ_SRC_EN_SRC_EN BIT(0) 752 - 753 - #define RSZ_SRC_MODE (0x0024) 754 - #define RSZ_SRC_MODE_OST BIT(0) 755 - #define RSZ_SRC_MODE_WRT BIT(1) 756 - 757 - #define RSZ_SRC_FMT0 (0x0028) 758 - #define RSZ_SRC_FMT0_BYPASS BIT(1) 759 - #define RSZ_SRC_FMT0_SEL BIT(0) 760 - 761 - #define RSZ_SRC_FMT1 (0x002c) 762 - #define RSZ_SRC_FMT1_IN420 BIT(1) 763 - 764 - #define RSZ_SRC_VPS (0x0030) 765 - #define RSZ_SRC_VSZ (0x0034) 766 - #define RSZ_SRC_HPS (0x0038) 767 - #define RSZ_SRC_HSZ (0x003c) 768 - #define RSZ_DMA_RZA (0x0040) 769 - #define RSZ_DMA_RZB (0x0044) 770 - #define RSZ_DMA_STA (0x0048) 771 - #define RSZ_GCK_MMR (0x004c) 772 - #define RSZ_GCK_MMR_MMR BIT(0) 773 - 774 - #define RSZ_GCK_SDR (0x0054) 775 - #define RSZ_GCK_SDR_CORE BIT(0) 776 - 777 - #define RSZ_IRQ_RZA (0x0058) 778 - #define RSZ_IRQ_RZA_MASK (0x1fff) 779 - 780 - #define RSZ_IRQ_RZB (0x005c) 781 - #define RSZ_IRQ_RZB_MASK (0x1fff) 782 - 783 - #define RSZ_YUV_Y_MIN (0x0060) 784 - #define RSZ_YUV_Y_MAX (0x0064) 785 - #define RSZ_YUV_C_MIN (0x0068) 786 - #define RSZ_YUV_C_MAX (0x006c) 787 - 788 - #define RSZ_SEQ (0x0074) 789 - #define RSZ_SEQ_HRVB BIT(2) 790 - #define RSZ_SEQ_HRVA BIT(0) 791 - 792 - #define RZA_EN (0x0078) 793 - #define RZA_MODE (0x007c) 794 - #define RZA_MODE_ONE_SHOT BIT(0) 795 - 796 - #define RZA_420 (0x0080) 797 - #define RZA_I_VPS (0x0084) 798 - #define RZA_I_HPS (0x0088) 799 - #define RZA_O_VSZ (0x008c) 800 - #define RZA_O_HSZ (0x0090) 801 - #define RZA_V_PHS_Y (0x0094) 802 - #define RZA_V_PHS_C (0x0098) 803 - #define RZA_V_DIF (0x009c) 804 - #define RZA_V_TYP (0x00a0) 805 - #define RZA_V_LPF (0x00a4) 806 - #define RZA_H_PHS (0x00a8) 807 - #define RZA_H_DIF (0x00b0) 808 - #define RZA_H_TYP (0x00b4) 809 - #define RZA_H_LPF (0x00b8) 810 - #define RZA_DWN_EN (0x00bc) 811 - #define RZA_SDR_Y_BAD_H (0x00d0) 812 - #define RZA_SDR_Y_BAD_L (0x00d4) 813 - #define RZA_SDR_Y_SAD_H (0x00d8) 814 - #define RZA_SDR_Y_SAD_L (0x00dc) 815 - #define RZA_SDR_Y_OFT (0x00e0) 816 - #define RZA_SDR_Y_PTR_S (0x00e4) 817 - #define RZA_SDR_Y_PTR_E (0x00e8) 818 - #define RZA_SDR_C_BAD_H (0x00ec) 819 - #define RZA_SDR_C_BAD_L (0x00f0) 820 - #define RZA_SDR_C_SAD_H (0x00f4) 821 - #define RZA_SDR_C_SAD_L (0x00f8) 822 - #define RZA_SDR_C_OFT (0x00fc) 823 - #define RZA_SDR_C_PTR_S (0x0100) 824 - #define RZA_SDR_C_PTR_E (0x0104) 825 - 826 - #define RZB_EN (0x0108) 827 - #define RZB_MODE (0x010c) 828 - #define RZB_420 (0x0110) 829 - #define RZB_I_VPS (0x0114) 830 - #define RZB_I_HPS (0x0118) 831 - #define RZB_O_VSZ (0x011c) 832 - #define RZB_O_HSZ (0x0120) 833 - 834 - #define RZB_V_DIF (0x012c) 835 - #define RZB_V_TYP (0x0130) 836 - #define RZB_V_LPF (0x0134) 837 - 838 - #define RZB_H_DIF (0x0140) 839 - #define RZB_H_TYP (0x0144) 840 - #define RZB_H_LPF (0x0148) 841 - 842 - #define RZB_SDR_Y_BAD_H (0x0160) 843 - #define RZB_SDR_Y_BAD_L (0x0164) 844 - #define RZB_SDR_Y_SAD_H (0x0168) 845 - #define RZB_SDR_Y_SAD_L (0x016c) 846 - #define RZB_SDR_Y_OFT (0x0170) 847 - #define RZB_SDR_Y_PTR_S (0x0174) 848 - #define RZB_SDR_Y_PTR_E (0x0178) 849 - #define RZB_SDR_C_BAD_H (0x017c) 850 - #define RZB_SDR_C_BAD_L (0x0180) 851 - #define RZB_SDR_C_SAD_H (0x0184) 852 - #define RZB_SDR_C_SAD_L (0x0188) 853 - 854 - #define RZB_SDR_C_PTR_S (0x0190) 855 - #define RZB_SDR_C_PTR_E (0x0194) 856 - 857 - /* Shared Bitmasks between RZA & RZB */ 858 - #define RSZ_EN_EN BIT(0) 859 - 860 - #define RSZ_420_CEN BIT(1) 861 - #define RSZ_420_YEN BIT(0) 862 - 863 - #define RSZ_I_VPS_MASK (0x1fff) 864 - 865 - #define RSZ_I_HPS_MASK (0x1fff) 866 - 867 - #define RSZ_O_VSZ_MASK (0x1fff) 868 - 869 - #define RSZ_O_HSZ_MASK (0x1ffe) 870 - 871 - #define RSZ_V_PHS_Y_MASK (0x3fff) 872 - 873 - #define RSZ_V_PHS_C_MASK (0x3fff) 874 - 875 - #define RSZ_V_DIF_MASK (0x3fff) 876 - 877 - #define RSZ_V_TYP_C BIT(1) 878 - #define RSZ_V_TYP_Y BIT(0) 879 - 880 - #define RSZ_V_LPF_C_MASK (0x3f << 6) 881 - #define RSZ_V_LPF_C_SHIFT 6 882 - #define RSZ_V_LPF_Y_MASK (0x3f << 0) 883 - #define RSZ_V_LPF_Y_SHIFT 0 884 - 885 - #define RSZ_H_PHS_MASK (0x3fff) 886 - 887 - #define RSZ_H_DIF_MASK (0x3fff) 888 - 889 - #define RSZ_H_TYP_C BIT(1) 890 - #define RSZ_H_TYP_Y BIT(0) 891 - 892 - #define RSZ_H_LPF_C_MASK (0x3f << 6) 893 - #define RSZ_H_LPF_C_SHIFT 6 894 - #define RSZ_H_LPF_Y_MASK (0x3f << 0) 895 - #define RSZ_H_LPF_Y_SHIFT 0 896 - 897 - #define RSZ_DWN_EN_DWN_EN BIT(0) 898 - 899 - #endif /* _OMAP4_ISS_REGS_H_ */
-884
drivers/staging/media/omap4iss/iss_resizer.c
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - ISP RESIZER module 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #include <linux/module.h> 11 - #include <linux/uaccess.h> 12 - #include <linux/delay.h> 13 - #include <linux/device.h> 14 - #include <linux/dma-mapping.h> 15 - #include <linux/mm.h> 16 - #include <linux/sched.h> 17 - 18 - #include "iss.h" 19 - #include "iss_regs.h" 20 - #include "iss_resizer.h" 21 - 22 - static const unsigned int resizer_fmts[] = { 23 - MEDIA_BUS_FMT_UYVY8_1X16, 24 - MEDIA_BUS_FMT_YUYV8_1X16, 25 - }; 26 - 27 - /* 28 - * resizer_print_status - Print current RESIZER Module register values. 29 - * @resizer: Pointer to ISS ISP RESIZER device. 30 - * 31 - * Also prints other debug information stored in the RESIZER module. 32 - */ 33 - #define RSZ_PRINT_REGISTER(iss, name)\ 34 - dev_dbg(iss->dev, "###RSZ " #name "=0x%08x\n", \ 35 - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_##name)) 36 - 37 - #define RZA_PRINT_REGISTER(iss, name)\ 38 - dev_dbg(iss->dev, "###RZA " #name "=0x%08x\n", \ 39 - iss_reg_read(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_##name)) 40 - 41 - static void resizer_print_status(struct iss_resizer_device *resizer) 42 - { 43 - struct iss_device *iss = to_iss_device(resizer); 44 - 45 - dev_dbg(iss->dev, "-------------RESIZER Register dump-------------\n"); 46 - 47 - RSZ_PRINT_REGISTER(iss, SYSCONFIG); 48 - RSZ_PRINT_REGISTER(iss, IN_FIFO_CTRL); 49 - RSZ_PRINT_REGISTER(iss, FRACDIV); 50 - RSZ_PRINT_REGISTER(iss, SRC_EN); 51 - RSZ_PRINT_REGISTER(iss, SRC_MODE); 52 - RSZ_PRINT_REGISTER(iss, SRC_FMT0); 53 - RSZ_PRINT_REGISTER(iss, SRC_FMT1); 54 - RSZ_PRINT_REGISTER(iss, SRC_VPS); 55 - RSZ_PRINT_REGISTER(iss, SRC_VSZ); 56 - RSZ_PRINT_REGISTER(iss, SRC_HPS); 57 - RSZ_PRINT_REGISTER(iss, SRC_HSZ); 58 - RSZ_PRINT_REGISTER(iss, DMA_RZA); 59 - RSZ_PRINT_REGISTER(iss, DMA_RZB); 60 - RSZ_PRINT_REGISTER(iss, DMA_STA); 61 - RSZ_PRINT_REGISTER(iss, GCK_MMR); 62 - RSZ_PRINT_REGISTER(iss, GCK_SDR); 63 - RSZ_PRINT_REGISTER(iss, IRQ_RZA); 64 - RSZ_PRINT_REGISTER(iss, IRQ_RZB); 65 - RSZ_PRINT_REGISTER(iss, YUV_Y_MIN); 66 - RSZ_PRINT_REGISTER(iss, YUV_Y_MAX); 67 - RSZ_PRINT_REGISTER(iss, YUV_C_MIN); 68 - RSZ_PRINT_REGISTER(iss, YUV_C_MAX); 69 - RSZ_PRINT_REGISTER(iss, SEQ); 70 - 71 - RZA_PRINT_REGISTER(iss, EN); 72 - RZA_PRINT_REGISTER(iss, MODE); 73 - RZA_PRINT_REGISTER(iss, 420); 74 - RZA_PRINT_REGISTER(iss, I_VPS); 75 - RZA_PRINT_REGISTER(iss, I_HPS); 76 - RZA_PRINT_REGISTER(iss, O_VSZ); 77 - RZA_PRINT_REGISTER(iss, O_HSZ); 78 - RZA_PRINT_REGISTER(iss, V_PHS_Y); 79 - RZA_PRINT_REGISTER(iss, V_PHS_C); 80 - RZA_PRINT_REGISTER(iss, V_DIF); 81 - RZA_PRINT_REGISTER(iss, V_TYP); 82 - RZA_PRINT_REGISTER(iss, V_LPF); 83 - RZA_PRINT_REGISTER(iss, H_PHS); 84 - RZA_PRINT_REGISTER(iss, H_DIF); 85 - RZA_PRINT_REGISTER(iss, H_TYP); 86 - RZA_PRINT_REGISTER(iss, H_LPF); 87 - RZA_PRINT_REGISTER(iss, DWN_EN); 88 - RZA_PRINT_REGISTER(iss, SDR_Y_BAD_H); 89 - RZA_PRINT_REGISTER(iss, SDR_Y_BAD_L); 90 - RZA_PRINT_REGISTER(iss, SDR_Y_SAD_H); 91 - RZA_PRINT_REGISTER(iss, SDR_Y_SAD_L); 92 - RZA_PRINT_REGISTER(iss, SDR_Y_OFT); 93 - RZA_PRINT_REGISTER(iss, SDR_Y_PTR_S); 94 - RZA_PRINT_REGISTER(iss, SDR_Y_PTR_E); 95 - RZA_PRINT_REGISTER(iss, SDR_C_BAD_H); 96 - RZA_PRINT_REGISTER(iss, SDR_C_BAD_L); 97 - RZA_PRINT_REGISTER(iss, SDR_C_SAD_H); 98 - RZA_PRINT_REGISTER(iss, SDR_C_SAD_L); 99 - RZA_PRINT_REGISTER(iss, SDR_C_OFT); 100 - RZA_PRINT_REGISTER(iss, SDR_C_PTR_S); 101 - RZA_PRINT_REGISTER(iss, SDR_C_PTR_E); 102 - 103 - dev_dbg(iss->dev, "-----------------------------------------------\n"); 104 - } 105 - 106 - /* 107 - * resizer_enable - Enable/Disable RESIZER. 108 - * @enable: enable flag 109 - * 110 - */ 111 - static void resizer_enable(struct iss_resizer_device *resizer, u8 enable) 112 - { 113 - struct iss_device *iss = to_iss_device(resizer); 114 - 115 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_EN, 116 - RSZ_SRC_EN_SRC_EN, enable ? RSZ_SRC_EN_SRC_EN : 0); 117 - 118 - /* TODO: Enable RSZB */ 119 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_EN, RSZ_EN_EN, 120 - enable ? RSZ_EN_EN : 0); 121 - } 122 - 123 - /* ----------------------------------------------------------------------------- 124 - * Format- and pipeline-related configuration helpers 125 - */ 126 - 127 - /* 128 - * resizer_set_outaddr - Set memory address to save output image 129 - * @resizer: Pointer to ISP RESIZER device. 130 - * @addr: 32-bit memory address aligned on 32 byte boundary. 131 - * 132 - * Sets the memory address where the output will be saved. 133 - */ 134 - static void resizer_set_outaddr(struct iss_resizer_device *resizer, u32 addr) 135 - { 136 - struct iss_device *iss = to_iss_device(resizer); 137 - struct v4l2_mbus_framefmt *informat, *outformat; 138 - 139 - informat = &resizer->formats[RESIZER_PAD_SINK]; 140 - outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM]; 141 - 142 - /* Save address split in Base Address H & L */ 143 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_BAD_H, 144 - (addr >> 16) & 0xffff); 145 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_BAD_L, 146 - addr & 0xffff); 147 - 148 - /* SAD = BAD */ 149 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_SAD_H, 150 - (addr >> 16) & 0xffff); 151 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_SAD_L, 152 - addr & 0xffff); 153 - 154 - /* Program UV buffer address... Hardcoded to be contiguous! */ 155 - if ((informat->code == MEDIA_BUS_FMT_UYVY8_1X16) && 156 - (outformat->code == MEDIA_BUS_FMT_YUYV8_1_5X8)) { 157 - u32 c_addr = addr + resizer->video_out.bpl_value 158 - * outformat->height; 159 - 160 - /* Ensure Y_BAD_L[6:0] = C_BAD_L[6:0]*/ 161 - if ((c_addr ^ addr) & 0x7f) { 162 - c_addr &= ~0x7f; 163 - c_addr += 0x80; 164 - c_addr |= addr & 0x7f; 165 - } 166 - 167 - /* Save address split in Base Address H & L */ 168 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_BAD_H, 169 - (c_addr >> 16) & 0xffff); 170 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_BAD_L, 171 - c_addr & 0xffff); 172 - 173 - /* SAD = BAD */ 174 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_SAD_H, 175 - (c_addr >> 16) & 0xffff); 176 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_SAD_L, 177 - c_addr & 0xffff); 178 - } 179 - } 180 - 181 - static void resizer_configure(struct iss_resizer_device *resizer) 182 - { 183 - struct iss_device *iss = to_iss_device(resizer); 184 - struct v4l2_mbus_framefmt *informat, *outformat; 185 - 186 - informat = &resizer->formats[RESIZER_PAD_SINK]; 187 - outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM]; 188 - 189 - /* Disable pass-through more. Despite its name, the BYPASS bit controls 190 - * pass-through mode, not bypass mode. 191 - */ 192 - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_FMT0, 193 - RSZ_SRC_FMT0_BYPASS); 194 - 195 - /* Select RSZ input */ 196 - iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_FMT0, 197 - RSZ_SRC_FMT0_SEL, 198 - resizer->input == RESIZER_INPUT_IPIPEIF ? 199 - RSZ_SRC_FMT0_SEL : 0); 200 - 201 - /* RSZ ignores WEN signal from IPIPE/IPIPEIF */ 202 - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_MODE, 203 - RSZ_SRC_MODE_WRT); 204 - 205 - /* Set Resizer in free-running mode */ 206 - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_MODE, 207 - RSZ_SRC_MODE_OST); 208 - 209 - /* Init Resizer A */ 210 - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_MODE, 211 - RZA_MODE_ONE_SHOT); 212 - 213 - /* Set size related things now */ 214 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_VPS, 0); 215 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_HPS, 0); 216 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_VSZ, 217 - informat->height - 2); 218 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_HSZ, 219 - informat->width - 1); 220 - 221 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_I_VPS, 0); 222 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_I_HPS, 0); 223 - 224 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_O_VSZ, 225 - outformat->height - 2); 226 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_O_HSZ, 227 - outformat->width - 1); 228 - 229 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_V_DIF, 0x100); 230 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_H_DIF, 0x100); 231 - 232 - /* Buffer output settings */ 233 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_PTR_S, 0); 234 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_PTR_E, 235 - outformat->height - 1); 236 - 237 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_OFT, 238 - resizer->video_out.bpl_value); 239 - 240 - /* UYVY -> NV12 conversion */ 241 - if ((informat->code == MEDIA_BUS_FMT_UYVY8_1X16) && 242 - (outformat->code == MEDIA_BUS_FMT_YUYV8_1_5X8)) { 243 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_420, 244 - RSZ_420_CEN | RSZ_420_YEN); 245 - 246 - /* UV Buffer output settings */ 247 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_PTR_S, 248 - 0); 249 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_PTR_E, 250 - outformat->height - 1); 251 - 252 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_OFT, 253 - resizer->video_out.bpl_value); 254 - } else { 255 - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_420, 0); 256 - } 257 - } 258 - 259 - /* ----------------------------------------------------------------------------- 260 - * Interrupt handling 261 - */ 262 - 263 - static void resizer_isr_buffer(struct iss_resizer_device *resizer) 264 - { 265 - struct iss_buffer *buffer; 266 - 267 - /* The whole resizer needs to be stopped. Disabling RZA only produces 268 - * input FIFO overflows, most probably when the next frame is received. 269 - */ 270 - resizer_enable(resizer, 0); 271 - 272 - buffer = omap4iss_video_buffer_next(&resizer->video_out); 273 - if (!buffer) 274 - return; 275 - 276 - resizer_set_outaddr(resizer, buffer->iss_addr); 277 - 278 - resizer_enable(resizer, 1); 279 - } 280 - 281 - /* 282 - * omap4iss_resizer_isr - Configure resizer during interframe time. 283 - * @resizer: Pointer to ISP RESIZER device. 284 - * @events: RESIZER events 285 - */ 286 - void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events) 287 - { 288 - struct iss_device *iss = to_iss_device(resizer); 289 - struct iss_pipeline *pipe = 290 - to_iss_pipeline(&resizer->subdev.entity); 291 - 292 - if (events & (ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | 293 - ISP5_IRQ_RSZ_FIFO_OVF)) { 294 - dev_dbg(iss->dev, "RSZ Err: FIFO_IN_BLK:%d, FIFO_OVF:%d\n", 295 - events & ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR ? 1 : 0, 296 - events & ISP5_IRQ_RSZ_FIFO_OVF ? 1 : 0); 297 - omap4iss_pipeline_cancel_stream(pipe); 298 - } 299 - 300 - if (omap4iss_module_sync_is_stopping(&resizer->wait, 301 - &resizer->stopping)) 302 - return; 303 - 304 - if (events & ISP5_IRQ_RSZ_INT_DMA) 305 - resizer_isr_buffer(resizer); 306 - } 307 - 308 - /* ----------------------------------------------------------------------------- 309 - * ISS video operations 310 - */ 311 - 312 - static int resizer_video_queue(struct iss_video *video, 313 - struct iss_buffer *buffer) 314 - { 315 - struct iss_resizer_device *resizer = container_of(video, 316 - struct iss_resizer_device, video_out); 317 - 318 - if (!(resizer->output & RESIZER_OUTPUT_MEMORY)) 319 - return -ENODEV; 320 - 321 - resizer_set_outaddr(resizer, buffer->iss_addr); 322 - 323 - /* 324 - * If streaming was enabled before there was a buffer queued 325 - * or underrun happened in the ISR, the hardware was not enabled 326 - * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set. 327 - * Enable it now. 328 - */ 329 - if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { 330 - resizer_enable(resizer, 1); 331 - iss_video_dmaqueue_flags_clr(video); 332 - } 333 - 334 - return 0; 335 - } 336 - 337 - static const struct iss_video_operations resizer_video_ops = { 338 - .queue = resizer_video_queue, 339 - }; 340 - 341 - /* ----------------------------------------------------------------------------- 342 - * V4L2 subdev operations 343 - */ 344 - 345 - /* 346 - * resizer_set_stream - Enable/Disable streaming on the RESIZER module 347 - * @sd: ISP RESIZER V4L2 subdevice 348 - * @enable: Enable/disable stream 349 - */ 350 - static int resizer_set_stream(struct v4l2_subdev *sd, int enable) 351 - { 352 - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); 353 - struct iss_device *iss = to_iss_device(resizer); 354 - struct iss_video *video_out = &resizer->video_out; 355 - int ret = 0; 356 - 357 - if (resizer->state == ISS_PIPELINE_STREAM_STOPPED) { 358 - if (enable == ISS_PIPELINE_STREAM_STOPPED) 359 - return 0; 360 - 361 - omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ); 362 - 363 - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_MMR, 364 - RSZ_GCK_MMR_MMR); 365 - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_SDR, 366 - RSZ_GCK_SDR_CORE); 367 - 368 - /* FIXME: Enable RSZB also */ 369 - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SYSCONFIG, 370 - RSZ_SYSCONFIG_RSZA_CLK_EN); 371 - } 372 - 373 - switch (enable) { 374 - case ISS_PIPELINE_STREAM_CONTINUOUS: 375 - 376 - resizer_configure(resizer); 377 - resizer_print_status(resizer); 378 - 379 - /* 380 - * When outputting to memory with no buffer available, let the 381 - * buffer queue handler start the hardware. A DMA queue flag 382 - * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is 383 - * a buffer available. 384 - */ 385 - if (resizer->output & RESIZER_OUTPUT_MEMORY && 386 - !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED)) 387 - break; 388 - 389 - atomic_set(&resizer->stopping, 0); 390 - resizer_enable(resizer, 1); 391 - iss_video_dmaqueue_flags_clr(video_out); 392 - break; 393 - 394 - case ISS_PIPELINE_STREAM_STOPPED: 395 - if (resizer->state == ISS_PIPELINE_STREAM_STOPPED) 396 - return 0; 397 - if (omap4iss_module_sync_idle(&sd->entity, &resizer->wait, 398 - &resizer->stopping)) 399 - ret = -ETIMEDOUT; 400 - 401 - resizer_enable(resizer, 0); 402 - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SYSCONFIG, 403 - RSZ_SYSCONFIG_RSZA_CLK_EN); 404 - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_SDR, 405 - RSZ_GCK_SDR_CORE); 406 - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_MMR, 407 - RSZ_GCK_MMR_MMR); 408 - omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ); 409 - iss_video_dmaqueue_flags_clr(video_out); 410 - break; 411 - } 412 - 413 - resizer->state = enable; 414 - return ret; 415 - } 416 - 417 - static struct v4l2_mbus_framefmt * 418 - __resizer_get_format(struct iss_resizer_device *resizer, 419 - struct v4l2_subdev_state *sd_state, unsigned int pad, 420 - enum v4l2_subdev_format_whence which) 421 - { 422 - if (which == V4L2_SUBDEV_FORMAT_TRY) 423 - return v4l2_subdev_state_get_format(sd_state, pad); 424 - return &resizer->formats[pad]; 425 - } 426 - 427 - /* 428 - * resizer_try_format - Try video format on a pad 429 - * @resizer: ISS RESIZER device 430 - * @sd_state: V4L2 subdev state 431 - * @pad: Pad number 432 - * @fmt: Format 433 - */ 434 - static void 435 - resizer_try_format(struct iss_resizer_device *resizer, 436 - struct v4l2_subdev_state *sd_state, unsigned int pad, 437 - struct v4l2_mbus_framefmt *fmt, 438 - enum v4l2_subdev_format_whence which) 439 - { 440 - u32 pixelcode; 441 - struct v4l2_mbus_framefmt *format; 442 - unsigned int width = fmt->width; 443 - unsigned int height = fmt->height; 444 - unsigned int i; 445 - 446 - switch (pad) { 447 - case RESIZER_PAD_SINK: 448 - for (i = 0; i < ARRAY_SIZE(resizer_fmts); i++) { 449 - if (fmt->code == resizer_fmts[i]) 450 - break; 451 - } 452 - 453 - /* If not found, use UYVY as default */ 454 - if (i >= ARRAY_SIZE(resizer_fmts)) 455 - fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; 456 - 457 - /* Clamp the input size. */ 458 - fmt->width = clamp_t(u32, width, 1, 8192); 459 - fmt->height = clamp_t(u32, height, 1, 8192); 460 - break; 461 - 462 - case RESIZER_PAD_SOURCE_MEM: 463 - pixelcode = fmt->code; 464 - format = __resizer_get_format(resizer, sd_state, 465 - RESIZER_PAD_SINK, 466 - which); 467 - memcpy(fmt, format, sizeof(*fmt)); 468 - 469 - if ((pixelcode == MEDIA_BUS_FMT_YUYV8_1_5X8) && 470 - (fmt->code == MEDIA_BUS_FMT_UYVY8_1X16)) 471 - fmt->code = pixelcode; 472 - 473 - /* The data formatter truncates the number of horizontal output 474 - * pixels to a multiple of 16. To avoid clipping data, allow 475 - * callers to request an output size bigger than the input size 476 - * up to the nearest multiple of 16. 477 - */ 478 - fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15); 479 - fmt->width &= ~15; 480 - fmt->height = clamp_t(u32, height, 32, fmt->height); 481 - break; 482 - } 483 - 484 - fmt->colorspace = V4L2_COLORSPACE_JPEG; 485 - fmt->field = V4L2_FIELD_NONE; 486 - } 487 - 488 - /* 489 - * resizer_enum_mbus_code - Handle pixel format enumeration 490 - * @sd : pointer to v4l2 subdev structure 491 - * @sd_state: V4L2 subdev state 492 - * @code : pointer to v4l2_subdev_mbus_code_enum structure 493 - * return -EINVAL or zero on success 494 - */ 495 - static int resizer_enum_mbus_code(struct v4l2_subdev *sd, 496 - struct v4l2_subdev_state *sd_state, 497 - struct v4l2_subdev_mbus_code_enum *code) 498 - { 499 - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); 500 - struct v4l2_mbus_framefmt *format; 501 - 502 - switch (code->pad) { 503 - case RESIZER_PAD_SINK: 504 - if (code->index >= ARRAY_SIZE(resizer_fmts)) 505 - return -EINVAL; 506 - 507 - code->code = resizer_fmts[code->index]; 508 - break; 509 - 510 - case RESIZER_PAD_SOURCE_MEM: 511 - format = __resizer_get_format(resizer, sd_state, 512 - RESIZER_PAD_SINK, 513 - code->which); 514 - 515 - if (code->index == 0) { 516 - code->code = format->code; 517 - break; 518 - } 519 - 520 - switch (format->code) { 521 - case MEDIA_BUS_FMT_UYVY8_1X16: 522 - if (code->index == 1) 523 - code->code = MEDIA_BUS_FMT_YUYV8_1_5X8; 524 - else 525 - return -EINVAL; 526 - break; 527 - default: 528 - if (code->index != 0) 529 - return -EINVAL; 530 - } 531 - 532 - break; 533 - 534 - default: 535 - return -EINVAL; 536 - } 537 - 538 - return 0; 539 - } 540 - 541 - static int resizer_enum_frame_size(struct v4l2_subdev *sd, 542 - struct v4l2_subdev_state *sd_state, 543 - struct v4l2_subdev_frame_size_enum *fse) 544 - { 545 - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); 546 - struct v4l2_mbus_framefmt format; 547 - 548 - if (fse->index != 0) 549 - return -EINVAL; 550 - 551 - format.code = fse->code; 552 - format.width = 1; 553 - format.height = 1; 554 - resizer_try_format(resizer, sd_state, fse->pad, &format, fse->which); 555 - fse->min_width = format.width; 556 - fse->min_height = format.height; 557 - 558 - if (format.code != fse->code) 559 - return -EINVAL; 560 - 561 - format.code = fse->code; 562 - format.width = -1; 563 - format.height = -1; 564 - resizer_try_format(resizer, sd_state, fse->pad, &format, fse->which); 565 - fse->max_width = format.width; 566 - fse->max_height = format.height; 567 - 568 - return 0; 569 - } 570 - 571 - /* 572 - * resizer_get_format - Retrieve the video format on a pad 573 - * @sd : ISP RESIZER V4L2 subdevice 574 - * @sd_state: V4L2 subdev state 575 - * @fmt: Format 576 - * 577 - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond 578 - * to the format type. 579 - */ 580 - static int resizer_get_format(struct v4l2_subdev *sd, 581 - struct v4l2_subdev_state *sd_state, 582 - struct v4l2_subdev_format *fmt) 583 - { 584 - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); 585 - struct v4l2_mbus_framefmt *format; 586 - 587 - format = __resizer_get_format(resizer, sd_state, fmt->pad, fmt->which); 588 - if (!format) 589 - return -EINVAL; 590 - 591 - fmt->format = *format; 592 - return 0; 593 - } 594 - 595 - /* 596 - * resizer_set_format - Set the video format on a pad 597 - * @sd : ISP RESIZER V4L2 subdevice 598 - * @sd_state: V4L2 subdev state 599 - * @fmt: Format 600 - * 601 - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond 602 - * to the format type. 603 - */ 604 - static int resizer_set_format(struct v4l2_subdev *sd, 605 - struct v4l2_subdev_state *sd_state, 606 - struct v4l2_subdev_format *fmt) 607 - { 608 - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); 609 - struct v4l2_mbus_framefmt *format; 610 - 611 - format = __resizer_get_format(resizer, sd_state, fmt->pad, fmt->which); 612 - if (!format) 613 - return -EINVAL; 614 - 615 - resizer_try_format(resizer, sd_state, fmt->pad, &fmt->format, 616 - fmt->which); 617 - *format = fmt->format; 618 - 619 - /* Propagate the format from sink to source */ 620 - if (fmt->pad == RESIZER_PAD_SINK) { 621 - format = __resizer_get_format(resizer, sd_state, 622 - RESIZER_PAD_SOURCE_MEM, 623 - fmt->which); 624 - *format = fmt->format; 625 - resizer_try_format(resizer, sd_state, RESIZER_PAD_SOURCE_MEM, 626 - format, 627 - fmt->which); 628 - } 629 - 630 - return 0; 631 - } 632 - 633 - static int resizer_link_validate(struct v4l2_subdev *sd, 634 - struct media_link *link, 635 - struct v4l2_subdev_format *source_fmt, 636 - struct v4l2_subdev_format *sink_fmt) 637 - { 638 - /* Check if the two ends match */ 639 - if (source_fmt->format.width != sink_fmt->format.width || 640 - source_fmt->format.height != sink_fmt->format.height) 641 - return -EPIPE; 642 - 643 - if (source_fmt->format.code != sink_fmt->format.code) 644 - return -EPIPE; 645 - 646 - return 0; 647 - } 648 - 649 - /* 650 - * resizer_init_formats - Initialize formats on all pads 651 - * @sd: ISP RESIZER V4L2 subdevice 652 - * @fh: V4L2 subdev file handle 653 - * 654 - * Initialize all pad formats with default values. If fh is not NULL, try 655 - * formats are initialized on the file handle. Otherwise active formats are 656 - * initialized on the device. 657 - */ 658 - static int resizer_init_formats(struct v4l2_subdev *sd, 659 - struct v4l2_subdev_fh *fh) 660 - { 661 - struct v4l2_subdev_format format; 662 - 663 - memset(&format, 0, sizeof(format)); 664 - format.pad = RESIZER_PAD_SINK; 665 - format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; 666 - format.format.code = MEDIA_BUS_FMT_UYVY8_1X16; 667 - format.format.width = 4096; 668 - format.format.height = 4096; 669 - resizer_set_format(sd, fh ? fh->state : NULL, &format); 670 - 671 - return 0; 672 - } 673 - 674 - /* V4L2 subdev video operations */ 675 - static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = { 676 - .s_stream = resizer_set_stream, 677 - }; 678 - 679 - /* V4L2 subdev pad operations */ 680 - static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = { 681 - .enum_mbus_code = resizer_enum_mbus_code, 682 - .enum_frame_size = resizer_enum_frame_size, 683 - .get_fmt = resizer_get_format, 684 - .set_fmt = resizer_set_format, 685 - .link_validate = resizer_link_validate, 686 - }; 687 - 688 - /* V4L2 subdev operations */ 689 - static const struct v4l2_subdev_ops resizer_v4l2_ops = { 690 - .video = &resizer_v4l2_video_ops, 691 - .pad = &resizer_v4l2_pad_ops, 692 - }; 693 - 694 - /* V4L2 subdev internal operations */ 695 - static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = { 696 - .open = resizer_init_formats, 697 - }; 698 - 699 - /* ----------------------------------------------------------------------------- 700 - * Media entity operations 701 - */ 702 - 703 - /* 704 - * resizer_link_setup - Setup RESIZER connections 705 - * @entity: RESIZER media entity 706 - * @local: Pad at the local end of the link 707 - * @remote: Pad at the remote end of the link 708 - * @flags: Link flags 709 - * 710 - * return -EINVAL or zero on success 711 - */ 712 - static int resizer_link_setup(struct media_entity *entity, 713 - const struct media_pad *local, 714 - const struct media_pad *remote, u32 flags) 715 - { 716 - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); 717 - struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); 718 - struct iss_device *iss = to_iss_device(resizer); 719 - unsigned int index = local->index; 720 - 721 - /* FIXME: this is actually a hack! */ 722 - if (is_media_entity_v4l2_subdev(remote->entity)) 723 - index |= 2 << 16; 724 - 725 - switch (index) { 726 - case RESIZER_PAD_SINK | 2 << 16: 727 - /* Read from IPIPE or IPIPEIF. */ 728 - if (!(flags & MEDIA_LNK_FL_ENABLED)) { 729 - resizer->input = RESIZER_INPUT_NONE; 730 - break; 731 - } 732 - 733 - if (resizer->input != RESIZER_INPUT_NONE) 734 - return -EBUSY; 735 - 736 - if (remote->entity == &iss->ipipeif.subdev.entity) 737 - resizer->input = RESIZER_INPUT_IPIPEIF; 738 - else if (remote->entity == &iss->ipipe.subdev.entity) 739 - resizer->input = RESIZER_INPUT_IPIPE; 740 - 741 - break; 742 - 743 - case RESIZER_PAD_SOURCE_MEM: 744 - /* Write to memory */ 745 - if (flags & MEDIA_LNK_FL_ENABLED) { 746 - if (resizer->output & ~RESIZER_OUTPUT_MEMORY) 747 - return -EBUSY; 748 - resizer->output |= RESIZER_OUTPUT_MEMORY; 749 - } else { 750 - resizer->output &= ~RESIZER_OUTPUT_MEMORY; 751 - } 752 - break; 753 - 754 - default: 755 - return -EINVAL; 756 - } 757 - 758 - return 0; 759 - } 760 - 761 - /* media operations */ 762 - static const struct media_entity_operations resizer_media_ops = { 763 - .link_setup = resizer_link_setup, 764 - .link_validate = v4l2_subdev_link_validate, 765 - }; 766 - 767 - /* 768 - * resizer_init_entities - Initialize V4L2 subdev and media entity 769 - * @resizer: ISS ISP RESIZER module 770 - * 771 - * Return 0 on success and a negative error code on failure. 772 - */ 773 - static int resizer_init_entities(struct iss_resizer_device *resizer) 774 - { 775 - struct v4l2_subdev *sd = &resizer->subdev; 776 - struct media_pad *pads = resizer->pads; 777 - struct media_entity *me = &sd->entity; 778 - int ret; 779 - 780 - resizer->input = RESIZER_INPUT_NONE; 781 - 782 - v4l2_subdev_init(sd, &resizer_v4l2_ops); 783 - sd->internal_ops = &resizer_v4l2_internal_ops; 784 - strscpy(sd->name, "OMAP4 ISS ISP resizer", sizeof(sd->name)); 785 - sd->grp_id = BIT(16); /* group ID for iss subdevs */ 786 - v4l2_set_subdevdata(sd, resizer); 787 - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 788 - 789 - pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 790 - pads[RESIZER_PAD_SOURCE_MEM].flags = MEDIA_PAD_FL_SOURCE; 791 - 792 - me->ops = &resizer_media_ops; 793 - ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads); 794 - if (ret < 0) 795 - return ret; 796 - 797 - resizer_init_formats(sd, NULL); 798 - 799 - resizer->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 800 - resizer->video_out.ops = &resizer_video_ops; 801 - resizer->video_out.iss = to_iss_device(resizer); 802 - resizer->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; 803 - resizer->video_out.bpl_alignment = 32; 804 - resizer->video_out.bpl_zero_padding = 1; 805 - resizer->video_out.bpl_max = 0x1ffe0; 806 - 807 - return omap4iss_video_init(&resizer->video_out, "ISP resizer a"); 808 - } 809 - 810 - void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer) 811 - { 812 - v4l2_device_unregister_subdev(&resizer->subdev); 813 - omap4iss_video_unregister(&resizer->video_out); 814 - } 815 - 816 - int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer, 817 - struct v4l2_device *vdev) 818 - { 819 - int ret; 820 - 821 - /* Register the subdev and video node. */ 822 - ret = v4l2_device_register_subdev(vdev, &resizer->subdev); 823 - if (ret < 0) 824 - goto error; 825 - 826 - ret = omap4iss_video_register(&resizer->video_out, vdev); 827 - if (ret < 0) 828 - goto error; 829 - 830 - return 0; 831 - 832 - error: 833 - omap4iss_resizer_unregister_entities(resizer); 834 - return ret; 835 - } 836 - 837 - /* ----------------------------------------------------------------------------- 838 - * ISP RESIZER initialisation and cleanup 839 - */ 840 - 841 - /* 842 - * omap4iss_resizer_init - RESIZER module initialization. 843 - * @iss: Device pointer specific to the OMAP4 ISS. 844 - * 845 - * TODO: Get the initialisation values from platform data. 846 - * 847 - * Return 0 on success or a negative error code otherwise. 848 - */ 849 - int omap4iss_resizer_init(struct iss_device *iss) 850 - { 851 - struct iss_resizer_device *resizer = &iss->resizer; 852 - 853 - resizer->state = ISS_PIPELINE_STREAM_STOPPED; 854 - init_waitqueue_head(&resizer->wait); 855 - 856 - return resizer_init_entities(resizer); 857 - } 858 - 859 - /* 860 - * omap4iss_resizer_create_links() - RESIZER pads links creation 861 - * @iss: Pointer to ISS device 862 - * 863 - * return negative error code or zero on success 864 - */ 865 - int omap4iss_resizer_create_links(struct iss_device *iss) 866 - { 867 - struct iss_resizer_device *resizer = &iss->resizer; 868 - 869 - /* Connect the RESIZER subdev to the video node. */ 870 - return media_create_pad_link(&resizer->subdev.entity, 871 - RESIZER_PAD_SOURCE_MEM, 872 - &resizer->video_out.video.entity, 0, 0); 873 - } 874 - 875 - /* 876 - * omap4iss_resizer_cleanup - RESIZER module cleanup. 877 - * @iss: Device pointer specific to the OMAP4 ISS. 878 - */ 879 - void omap4iss_resizer_cleanup(struct iss_device *iss) 880 - { 881 - struct iss_resizer_device *resizer = &iss->resizer; 882 - 883 - media_entity_cleanup(&resizer->subdev.entity); 884 - }
-72
drivers/staging/media/omap4iss/iss_resizer.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ */ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - ISP RESIZER module 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #ifndef OMAP4_ISS_RESIZER_H 11 - #define OMAP4_ISS_RESIZER_H 12 - 13 - #include "iss_video.h" 14 - 15 - enum resizer_input_entity { 16 - RESIZER_INPUT_NONE, 17 - RESIZER_INPUT_IPIPE, 18 - RESIZER_INPUT_IPIPEIF 19 - }; 20 - 21 - #define RESIZER_OUTPUT_MEMORY BIT(0) 22 - 23 - /* Sink and source RESIZER pads */ 24 - #define RESIZER_PAD_SINK 0 25 - #define RESIZER_PAD_SOURCE_MEM 1 26 - #define RESIZER_PADS_NUM 2 27 - 28 - /* 29 - * struct iss_resizer_device - Structure for the RESIZER module to store its own 30 - * information 31 - * @subdev: V4L2 subdevice 32 - * @pads: Sink and source media entity pads 33 - * @formats: Active video formats 34 - * @input: Active input 35 - * @output: Active outputs 36 - * @video_out: Output video node 37 - * @error: A hardware error occurred during capture 38 - * @state: Streaming state 39 - * @wait: Wait queue used to stop the module 40 - * @stopping: Stopping state 41 - */ 42 - struct iss_resizer_device { 43 - struct v4l2_subdev subdev; 44 - struct media_pad pads[RESIZER_PADS_NUM]; 45 - struct v4l2_mbus_framefmt formats[RESIZER_PADS_NUM]; 46 - 47 - enum resizer_input_entity input; 48 - unsigned int output; 49 - struct iss_video video_out; 50 - unsigned int error; 51 - 52 - enum iss_pipeline_stream_state state; 53 - wait_queue_head_t wait; 54 - atomic_t stopping; 55 - }; 56 - 57 - struct iss_device; 58 - 59 - int omap4iss_resizer_init(struct iss_device *iss); 60 - int omap4iss_resizer_create_links(struct iss_device *iss); 61 - void omap4iss_resizer_cleanup(struct iss_device *iss); 62 - int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer, 63 - struct v4l2_device *vdev); 64 - void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer); 65 - 66 - int omap4iss_resizer_busy(struct iss_resizer_device *resizer); 67 - void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events); 68 - void omap4iss_resizer_restore_context(struct iss_device *iss); 69 - void omap4iss_resizer_max_rate(struct iss_resizer_device *resizer, 70 - unsigned int *max_rate); 71 - 72 - #endif /* OMAP4_ISS_RESIZER_H */
-1274
drivers/staging/media/omap4iss/iss_video.c
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - Generic video node 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #include <linux/clk.h> 11 - #include <linux/mm.h> 12 - #include <linux/pagemap.h> 13 - #include <linux/sched.h> 14 - #include <linux/slab.h> 15 - #include <linux/vmalloc.h> 16 - #include <linux/module.h> 17 - 18 - #include <media/v4l2-dev.h> 19 - #include <media/v4l2-ioctl.h> 20 - #include <media/v4l2-mc.h> 21 - 22 - #include "iss_video.h" 23 - #include "iss.h" 24 - 25 - /* ----------------------------------------------------------------------------- 26 - * Helper functions 27 - */ 28 - 29 - static struct iss_format_info formats[] = { 30 - { MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8, 31 - MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8, 32 - V4L2_PIX_FMT_GREY, 8, }, 33 - { MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y10_1X10, 34 - MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y8_1X8, 35 - V4L2_PIX_FMT_Y10, 10, }, 36 - { MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y10_1X10, 37 - MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y8_1X8, 38 - V4L2_PIX_FMT_Y12, 12, }, 39 - { MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8, 40 - MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8, 41 - V4L2_PIX_FMT_SBGGR8, 8, }, 42 - { MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, 43 - MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, 44 - V4L2_PIX_FMT_SGBRG8, 8, }, 45 - { MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8, 46 - MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8, 47 - V4L2_PIX_FMT_SGRBG8, 8, }, 48 - { MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8, 49 - MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8, 50 - V4L2_PIX_FMT_SRGGB8, 8, }, 51 - { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, 52 - MEDIA_BUS_FMT_SGRBG10_1X10, 0, 53 - V4L2_PIX_FMT_SGRBG10DPCM8, 8, }, 54 - { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, 55 - MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR8_1X8, 56 - V4L2_PIX_FMT_SBGGR10, 10, }, 57 - { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10, 58 - MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG8_1X8, 59 - V4L2_PIX_FMT_SGBRG10, 10, }, 60 - { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, 61 - MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG8_1X8, 62 - V4L2_PIX_FMT_SGRBG10, 10, }, 63 - { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10, 64 - MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB8_1X8, 65 - V4L2_PIX_FMT_SRGGB10, 10, }, 66 - { MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR10_1X10, 67 - MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR8_1X8, 68 - V4L2_PIX_FMT_SBGGR12, 12, }, 69 - { MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG10_1X10, 70 - MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG8_1X8, 71 - V4L2_PIX_FMT_SGBRG12, 12, }, 72 - { MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG10_1X10, 73 - MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG8_1X8, 74 - V4L2_PIX_FMT_SGRBG12, 12, }, 75 - { MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB10_1X10, 76 - MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB8_1X8, 77 - V4L2_PIX_FMT_SRGGB12, 12, }, 78 - { MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_UYVY8_1X16, 79 - MEDIA_BUS_FMT_UYVY8_1X16, 0, 80 - V4L2_PIX_FMT_UYVY, 16, }, 81 - { MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YUYV8_1X16, 82 - MEDIA_BUS_FMT_YUYV8_1X16, 0, 83 - V4L2_PIX_FMT_YUYV, 16, }, 84 - { MEDIA_BUS_FMT_YUYV8_1_5X8, MEDIA_BUS_FMT_YUYV8_1_5X8, 85 - MEDIA_BUS_FMT_YUYV8_1_5X8, 0, 86 - V4L2_PIX_FMT_NV12, 8, }, 87 - }; 88 - 89 - const struct iss_format_info * 90 - omap4iss_video_format_info(u32 code) 91 - { 92 - unsigned int i; 93 - 94 - for (i = 0; i < ARRAY_SIZE(formats); ++i) { 95 - if (formats[i].code == code) 96 - return &formats[i]; 97 - } 98 - 99 - return NULL; 100 - } 101 - 102 - /* 103 - * iss_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format 104 - * @video: ISS video instance 105 - * @mbus: v4l2_mbus_framefmt format (input) 106 - * @pix: v4l2_pix_format format (output) 107 - * 108 - * Fill the output pix structure with information from the input mbus format. 109 - * The bytesperline and sizeimage fields are computed from the requested bytes 110 - * per line value in the pix format and information from the video instance. 111 - * 112 - * Return the number of padding bytes at end of line. 113 - */ 114 - static unsigned int iss_video_mbus_to_pix(const struct iss_video *video, 115 - const struct v4l2_mbus_framefmt *mbus, 116 - struct v4l2_pix_format *pix) 117 - { 118 - unsigned int bpl = pix->bytesperline; 119 - unsigned int min_bpl; 120 - unsigned int i; 121 - 122 - memset(pix, 0, sizeof(*pix)); 123 - pix->width = mbus->width; 124 - pix->height = mbus->height; 125 - 126 - /* 127 - * Skip the last format in the loop so that it will be selected if no 128 - * match is found. 129 - */ 130 - for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) { 131 - if (formats[i].code == mbus->code) 132 - break; 133 - } 134 - 135 - min_bpl = pix->width * ALIGN(formats[i].bpp, 8) / 8; 136 - 137 - /* 138 - * Clamp the requested bytes per line value. If the maximum bytes per 139 - * line value is zero, the module doesn't support user configurable line 140 - * sizes. Override the requested value with the minimum in that case. 141 - */ 142 - if (video->bpl_max) 143 - bpl = clamp(bpl, min_bpl, video->bpl_max); 144 - else 145 - bpl = min_bpl; 146 - 147 - if (!video->bpl_zero_padding || bpl != min_bpl) 148 - bpl = ALIGN(bpl, video->bpl_alignment); 149 - 150 - pix->pixelformat = formats[i].pixelformat; 151 - pix->bytesperline = bpl; 152 - pix->sizeimage = pix->bytesperline * pix->height; 153 - pix->colorspace = mbus->colorspace; 154 - pix->field = mbus->field; 155 - 156 - /* FIXME: Special case for NV12! We should make this nicer... */ 157 - if (pix->pixelformat == V4L2_PIX_FMT_NV12) 158 - pix->sizeimage += (pix->bytesperline * pix->height) / 2; 159 - 160 - return bpl - min_bpl; 161 - } 162 - 163 - static void iss_video_pix_to_mbus(const struct v4l2_pix_format *pix, 164 - struct v4l2_mbus_framefmt *mbus) 165 - { 166 - unsigned int i; 167 - 168 - memset(mbus, 0, sizeof(*mbus)); 169 - mbus->width = pix->width; 170 - mbus->height = pix->height; 171 - 172 - /* 173 - * Skip the last format in the loop so that it will be selected if no 174 - * match is found. 175 - */ 176 - for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) { 177 - if (formats[i].pixelformat == pix->pixelformat) 178 - break; 179 - } 180 - 181 - mbus->code = formats[i].code; 182 - mbus->colorspace = pix->colorspace; 183 - mbus->field = pix->field; 184 - } 185 - 186 - static struct v4l2_subdev * 187 - iss_video_remote_subdev(struct iss_video *video, u32 *pad) 188 - { 189 - struct media_pad *remote; 190 - 191 - remote = media_pad_remote_pad_first(&video->pad); 192 - 193 - if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) 194 - return NULL; 195 - 196 - if (pad) 197 - *pad = remote->index; 198 - 199 - return media_entity_to_v4l2_subdev(remote->entity); 200 - } 201 - 202 - /* Return a pointer to the ISS video instance at the far end of the pipeline. */ 203 - static struct iss_video * 204 - iss_video_far_end(struct iss_video *video, struct iss_pipeline *pipe) 205 - { 206 - struct media_pipeline_entity_iter iter; 207 - struct media_entity *entity; 208 - struct iss_video *far_end = NULL; 209 - int ret; 210 - 211 - ret = media_pipeline_entity_iter_init(&pipe->pipe, &iter); 212 - if (ret) 213 - return ERR_PTR(-ENOMEM); 214 - 215 - media_pipeline_for_each_entity(&pipe->pipe, &iter, entity) { 216 - struct iss_video *other; 217 - 218 - if (entity == &video->video.entity) 219 - continue; 220 - 221 - if (!is_media_entity_v4l2_video_device(entity)) 222 - continue; 223 - 224 - other = to_iss_video(media_entity_to_video_device(entity)); 225 - if (other->type != video->type) { 226 - far_end = other; 227 - break; 228 - } 229 - } 230 - 231 - media_pipeline_entity_iter_cleanup(&iter); 232 - 233 - return far_end; 234 - } 235 - 236 - static int 237 - __iss_video_get_format(struct iss_video *video, 238 - struct v4l2_mbus_framefmt *format) 239 - { 240 - struct v4l2_subdev_format fmt = { 241 - .which = V4L2_SUBDEV_FORMAT_ACTIVE, 242 - }; 243 - struct v4l2_subdev *subdev; 244 - u32 pad; 245 - int ret; 246 - 247 - subdev = iss_video_remote_subdev(video, &pad); 248 - if (!subdev) 249 - return -EINVAL; 250 - 251 - fmt.pad = pad; 252 - 253 - mutex_lock(&video->mutex); 254 - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); 255 - mutex_unlock(&video->mutex); 256 - 257 - if (ret) 258 - return ret; 259 - 260 - *format = fmt.format; 261 - return 0; 262 - } 263 - 264 - static int 265 - iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh) 266 - { 267 - struct v4l2_mbus_framefmt format; 268 - struct v4l2_pix_format pixfmt; 269 - int ret; 270 - 271 - ret = __iss_video_get_format(video, &format); 272 - if (ret < 0) 273 - return ret; 274 - 275 - pixfmt.bytesperline = 0; 276 - ret = iss_video_mbus_to_pix(video, &format, &pixfmt); 277 - 278 - if (vfh->format.fmt.pix.pixelformat != pixfmt.pixelformat || 279 - vfh->format.fmt.pix.height != pixfmt.height || 280 - vfh->format.fmt.pix.width != pixfmt.width || 281 - vfh->format.fmt.pix.bytesperline != pixfmt.bytesperline || 282 - vfh->format.fmt.pix.sizeimage != pixfmt.sizeimage) 283 - return -EINVAL; 284 - 285 - return ret; 286 - } 287 - 288 - /* ----------------------------------------------------------------------------- 289 - * Video queue operations 290 - */ 291 - 292 - static int iss_video_queue_setup(struct vb2_queue *vq, 293 - unsigned int *count, unsigned int *num_planes, 294 - unsigned int sizes[], 295 - struct device *alloc_devs[]) 296 - { 297 - struct iss_video_fh *vfh = vb2_get_drv_priv(vq); 298 - struct iss_video *video = vfh->video; 299 - 300 - /* Revisit multi-planar support for NV12 */ 301 - *num_planes = 1; 302 - 303 - sizes[0] = vfh->format.fmt.pix.sizeimage; 304 - if (sizes[0] == 0) 305 - return -EINVAL; 306 - 307 - *count = min(*count, video->capture_mem / PAGE_ALIGN(sizes[0])); 308 - 309 - return 0; 310 - } 311 - 312 - static void iss_video_buf_cleanup(struct vb2_buffer *vb) 313 - { 314 - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 315 - struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb); 316 - 317 - if (buffer->iss_addr) 318 - buffer->iss_addr = 0; 319 - } 320 - 321 - static int iss_video_buf_prepare(struct vb2_buffer *vb) 322 - { 323 - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 324 - struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue); 325 - struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb); 326 - struct iss_video *video = vfh->video; 327 - unsigned long size = vfh->format.fmt.pix.sizeimage; 328 - dma_addr_t addr; 329 - 330 - if (vb2_plane_size(vb, 0) < size) 331 - return -ENOBUFS; 332 - 333 - addr = vb2_dma_contig_plane_dma_addr(vb, 0); 334 - if (!IS_ALIGNED(addr, 32)) { 335 - dev_dbg(video->iss->dev, 336 - "Buffer address must be aligned to 32 bytes boundary.\n"); 337 - return -EINVAL; 338 - } 339 - 340 - vb2_set_plane_payload(vb, 0, size); 341 - buffer->iss_addr = addr; 342 - return 0; 343 - } 344 - 345 - static void iss_video_buf_queue(struct vb2_buffer *vb) 346 - { 347 - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 348 - struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue); 349 - struct iss_video *video = vfh->video; 350 - struct iss_buffer *buffer = container_of(vbuf, struct iss_buffer, vb); 351 - struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity); 352 - unsigned long flags; 353 - bool empty; 354 - 355 - spin_lock_irqsave(&video->qlock, flags); 356 - 357 - /* 358 - * Mark the buffer is faulty and give it back to the queue immediately 359 - * if the video node has registered an error. vb2 will perform the same 360 - * check when preparing the buffer, but that is inherently racy, so we 361 - * need to handle the race condition with an authoritative check here. 362 - */ 363 - if (unlikely(video->error)) { 364 - vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); 365 - spin_unlock_irqrestore(&video->qlock, flags); 366 - return; 367 - } 368 - 369 - empty = list_empty(&video->dmaqueue); 370 - list_add_tail(&buffer->list, &video->dmaqueue); 371 - 372 - spin_unlock_irqrestore(&video->qlock, flags); 373 - 374 - if (empty) { 375 - enum iss_pipeline_state state; 376 - unsigned int start; 377 - 378 - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 379 - state = ISS_PIPELINE_QUEUE_OUTPUT; 380 - else 381 - state = ISS_PIPELINE_QUEUE_INPUT; 382 - 383 - spin_lock_irqsave(&pipe->lock, flags); 384 - pipe->state |= state; 385 - video->ops->queue(video, buffer); 386 - video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_QUEUED; 387 - 388 - start = iss_pipeline_ready(pipe); 389 - if (start) 390 - pipe->state |= ISS_PIPELINE_STREAM; 391 - spin_unlock_irqrestore(&pipe->lock, flags); 392 - 393 - if (start) 394 - omap4iss_pipeline_set_stream(pipe, 395 - ISS_PIPELINE_STREAM_SINGLESHOT); 396 - } 397 - } 398 - 399 - static const struct vb2_ops iss_video_vb2ops = { 400 - .queue_setup = iss_video_queue_setup, 401 - .buf_prepare = iss_video_buf_prepare, 402 - .buf_queue = iss_video_buf_queue, 403 - .buf_cleanup = iss_video_buf_cleanup, 404 - }; 405 - 406 - /* 407 - * omap4iss_video_buffer_next - Complete the current buffer and return the next 408 - * @video: ISS video object 409 - * 410 - * Remove the current video buffer from the DMA queue and fill its timestamp, 411 - * field count and state fields before waking up its completion handler. 412 - * 413 - * For capture video nodes, the buffer state is set to VB2_BUF_STATE_DONE if no 414 - * error has been flagged in the pipeline, or to VB2_BUF_STATE_ERROR otherwise. 415 - * 416 - * The DMA queue is expected to contain at least one buffer. 417 - * 418 - * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is 419 - * empty. 420 - */ 421 - struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video) 422 - { 423 - struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity); 424 - enum iss_pipeline_state state; 425 - struct iss_buffer *buf; 426 - unsigned long flags; 427 - 428 - spin_lock_irqsave(&video->qlock, flags); 429 - if (WARN_ON(list_empty(&video->dmaqueue))) { 430 - spin_unlock_irqrestore(&video->qlock, flags); 431 - return NULL; 432 - } 433 - 434 - buf = list_first_entry(&video->dmaqueue, struct iss_buffer, 435 - list); 436 - list_del(&buf->list); 437 - spin_unlock_irqrestore(&video->qlock, flags); 438 - 439 - buf->vb.vb2_buf.timestamp = ktime_get_ns(); 440 - 441 - /* 442 - * Do frame number propagation only if this is the output video node. 443 - * Frame number either comes from the CSI receivers or it gets 444 - * incremented here if H3A is not active. 445 - * Note: There is no guarantee that the output buffer will finish 446 - * first, so the input number might lag behind by 1 in some cases. 447 - */ 448 - if (video == pipe->output && !pipe->do_propagation) 449 - buf->vb.sequence = 450 - atomic_inc_return(&pipe->frame_number); 451 - else 452 - buf->vb.sequence = atomic_read(&pipe->frame_number); 453 - 454 - vb2_buffer_done(&buf->vb.vb2_buf, pipe->error ? 455 - VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); 456 - pipe->error = false; 457 - 458 - spin_lock_irqsave(&video->qlock, flags); 459 - if (list_empty(&video->dmaqueue)) { 460 - spin_unlock_irqrestore(&video->qlock, flags); 461 - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 462 - state = ISS_PIPELINE_QUEUE_OUTPUT 463 - | ISS_PIPELINE_STREAM; 464 - else 465 - state = ISS_PIPELINE_QUEUE_INPUT 466 - | ISS_PIPELINE_STREAM; 467 - 468 - spin_lock_irqsave(&pipe->lock, flags); 469 - pipe->state &= ~state; 470 - if (video->pipe.stream_state == ISS_PIPELINE_STREAM_CONTINUOUS) 471 - video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_UNDERRUN; 472 - spin_unlock_irqrestore(&pipe->lock, flags); 473 - return NULL; 474 - } 475 - 476 - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input) { 477 - spin_lock(&pipe->lock); 478 - pipe->state &= ~ISS_PIPELINE_STREAM; 479 - spin_unlock(&pipe->lock); 480 - } 481 - 482 - buf = list_first_entry(&video->dmaqueue, struct iss_buffer, 483 - list); 484 - spin_unlock_irqrestore(&video->qlock, flags); 485 - buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; 486 - return buf; 487 - } 488 - 489 - /* 490 - * omap4iss_video_cancel_stream - Cancel stream on a video node 491 - * @video: ISS video object 492 - * 493 - * Cancelling a stream mark all buffers on the video node as erroneous and makes 494 - * sure no new buffer can be queued. 495 - */ 496 - void omap4iss_video_cancel_stream(struct iss_video *video) 497 - { 498 - unsigned long flags; 499 - 500 - spin_lock_irqsave(&video->qlock, flags); 501 - 502 - while (!list_empty(&video->dmaqueue)) { 503 - struct iss_buffer *buf; 504 - 505 - buf = list_first_entry(&video->dmaqueue, struct iss_buffer, 506 - list); 507 - list_del(&buf->list); 508 - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 509 - } 510 - 511 - vb2_queue_error(video->queue); 512 - video->error = true; 513 - 514 - spin_unlock_irqrestore(&video->qlock, flags); 515 - } 516 - 517 - /* ----------------------------------------------------------------------------- 518 - * V4L2 ioctls 519 - */ 520 - 521 - static int 522 - iss_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) 523 - { 524 - struct iss_video *video = video_drvdata(file); 525 - 526 - strscpy(cap->driver, ISS_VIDEO_DRIVER_NAME, sizeof(cap->driver)); 527 - strscpy(cap->card, video->video.name, sizeof(cap->card)); 528 - strscpy(cap->bus_info, "media", sizeof(cap->bus_info)); 529 - cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING 530 - | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT; 531 - 532 - return 0; 533 - } 534 - 535 - static int 536 - iss_video_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) 537 - { 538 - struct iss_video *video = video_drvdata(file); 539 - struct v4l2_mbus_framefmt format; 540 - unsigned int index = f->index; 541 - unsigned int i; 542 - int ret; 543 - 544 - if (f->type != video->type) 545 - return -EINVAL; 546 - 547 - ret = __iss_video_get_format(video, &format); 548 - if (ret < 0) 549 - return ret; 550 - 551 - for (i = 0; i < ARRAY_SIZE(formats); ++i) { 552 - const struct iss_format_info *info = &formats[i]; 553 - 554 - if (format.code != info->code) 555 - continue; 556 - 557 - if (index == 0) { 558 - f->pixelformat = info->pixelformat; 559 - return 0; 560 - } 561 - 562 - index--; 563 - } 564 - 565 - return -EINVAL; 566 - } 567 - 568 - static int 569 - iss_video_get_format(struct file *file, void *fh, struct v4l2_format *format) 570 - { 571 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 572 - struct iss_video *video = video_drvdata(file); 573 - 574 - if (format->type != video->type) 575 - return -EINVAL; 576 - 577 - mutex_lock(&video->mutex); 578 - *format = vfh->format; 579 - mutex_unlock(&video->mutex); 580 - 581 - return 0; 582 - } 583 - 584 - static int 585 - iss_video_set_format(struct file *file, void *fh, struct v4l2_format *format) 586 - { 587 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 588 - struct iss_video *video = video_drvdata(file); 589 - struct v4l2_mbus_framefmt fmt; 590 - 591 - if (format->type != video->type) 592 - return -EINVAL; 593 - 594 - mutex_lock(&video->mutex); 595 - 596 - /* 597 - * Fill the bytesperline and sizeimage fields by converting to media bus 598 - * format and back to pixel format. 599 - */ 600 - iss_video_pix_to_mbus(&format->fmt.pix, &fmt); 601 - iss_video_mbus_to_pix(video, &fmt, &format->fmt.pix); 602 - 603 - vfh->format = *format; 604 - 605 - mutex_unlock(&video->mutex); 606 - return 0; 607 - } 608 - 609 - static int 610 - iss_video_try_format(struct file *file, void *fh, struct v4l2_format *format) 611 - { 612 - struct iss_video *video = video_drvdata(file); 613 - struct v4l2_subdev_format fmt = { 614 - .which = V4L2_SUBDEV_FORMAT_ACTIVE, 615 - }; 616 - struct v4l2_subdev *subdev; 617 - u32 pad; 618 - int ret; 619 - 620 - if (format->type != video->type) 621 - return -EINVAL; 622 - 623 - subdev = iss_video_remote_subdev(video, &pad); 624 - if (!subdev) 625 - return -EINVAL; 626 - 627 - iss_video_pix_to_mbus(&format->fmt.pix, &fmt.format); 628 - 629 - fmt.pad = pad; 630 - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); 631 - if (ret) 632 - return ret; 633 - 634 - iss_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix); 635 - return 0; 636 - } 637 - 638 - static int 639 - iss_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel) 640 - { 641 - struct iss_video *video = video_drvdata(file); 642 - struct v4l2_subdev_format format = { 643 - .which = V4L2_SUBDEV_FORMAT_ACTIVE, 644 - }; 645 - struct v4l2_subdev *subdev; 646 - struct v4l2_subdev_selection sdsel = { 647 - .which = V4L2_SUBDEV_FORMAT_ACTIVE, 648 - .target = sel->target, 649 - }; 650 - u32 pad; 651 - int ret; 652 - 653 - switch (sel->target) { 654 - case V4L2_SEL_TGT_CROP: 655 - case V4L2_SEL_TGT_CROP_BOUNDS: 656 - case V4L2_SEL_TGT_CROP_DEFAULT: 657 - if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 658 - return -EINVAL; 659 - break; 660 - case V4L2_SEL_TGT_COMPOSE: 661 - case V4L2_SEL_TGT_COMPOSE_BOUNDS: 662 - case V4L2_SEL_TGT_COMPOSE_DEFAULT: 663 - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 664 - return -EINVAL; 665 - break; 666 - default: 667 - return -EINVAL; 668 - } 669 - subdev = iss_video_remote_subdev(video, &pad); 670 - if (!subdev) 671 - return -EINVAL; 672 - 673 - /* 674 - * Try the get selection operation first and fallback to get format if 675 - * not implemented. 676 - */ 677 - sdsel.pad = pad; 678 - ret = v4l2_subdev_call(subdev, pad, get_selection, NULL, &sdsel); 679 - if (!ret) 680 - sel->r = sdsel.r; 681 - if (ret != -ENOIOCTLCMD) 682 - return ret; 683 - 684 - format.pad = pad; 685 - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format); 686 - if (ret < 0) 687 - return ret == -ENOIOCTLCMD ? -ENOTTY : ret; 688 - 689 - sel->r.left = 0; 690 - sel->r.top = 0; 691 - sel->r.width = format.format.width; 692 - sel->r.height = format.format.height; 693 - 694 - return 0; 695 - } 696 - 697 - static int 698 - iss_video_set_selection(struct file *file, void *fh, struct v4l2_selection *sel) 699 - { 700 - struct iss_video *video = video_drvdata(file); 701 - struct v4l2_subdev *subdev; 702 - struct v4l2_subdev_selection sdsel = { 703 - .which = V4L2_SUBDEV_FORMAT_ACTIVE, 704 - .target = sel->target, 705 - .flags = sel->flags, 706 - .r = sel->r, 707 - }; 708 - u32 pad; 709 - int ret; 710 - 711 - switch (sel->target) { 712 - case V4L2_SEL_TGT_CROP: 713 - if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 714 - return -EINVAL; 715 - break; 716 - case V4L2_SEL_TGT_COMPOSE: 717 - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 718 - return -EINVAL; 719 - break; 720 - default: 721 - return -EINVAL; 722 - } 723 - subdev = iss_video_remote_subdev(video, &pad); 724 - if (!subdev) 725 - return -EINVAL; 726 - 727 - sdsel.pad = pad; 728 - mutex_lock(&video->mutex); 729 - ret = v4l2_subdev_call(subdev, pad, set_selection, NULL, &sdsel); 730 - mutex_unlock(&video->mutex); 731 - if (!ret) 732 - sel->r = sdsel.r; 733 - 734 - return ret == -ENOIOCTLCMD ? -ENOTTY : ret; 735 - } 736 - 737 - static int 738 - iss_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a) 739 - { 740 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 741 - struct iss_video *video = video_drvdata(file); 742 - 743 - if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || 744 - video->type != a->type) 745 - return -EINVAL; 746 - 747 - memset(a, 0, sizeof(*a)); 748 - a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 749 - a->parm.output.capability = V4L2_CAP_TIMEPERFRAME; 750 - a->parm.output.timeperframe = vfh->timeperframe; 751 - 752 - return 0; 753 - } 754 - 755 - static int 756 - iss_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a) 757 - { 758 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 759 - struct iss_video *video = video_drvdata(file); 760 - 761 - if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || 762 - video->type != a->type) 763 - return -EINVAL; 764 - 765 - if (a->parm.output.timeperframe.denominator == 0) 766 - a->parm.output.timeperframe.denominator = 1; 767 - 768 - vfh->timeperframe = a->parm.output.timeperframe; 769 - 770 - return 0; 771 - } 772 - 773 - static int 774 - iss_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb) 775 - { 776 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 777 - 778 - return vb2_reqbufs(&vfh->queue, rb); 779 - } 780 - 781 - static int 782 - iss_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) 783 - { 784 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 785 - 786 - return vb2_querybuf(&vfh->queue, b); 787 - } 788 - 789 - static int 790 - iss_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) 791 - { 792 - struct iss_video *video = video_drvdata(file); 793 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 794 - 795 - return vb2_qbuf(&vfh->queue, video->video.v4l2_dev->mdev, b); 796 - } 797 - 798 - static int 799 - iss_video_expbuf(struct file *file, void *fh, struct v4l2_exportbuffer *e) 800 - { 801 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 802 - 803 - return vb2_expbuf(&vfh->queue, e); 804 - } 805 - 806 - static int 807 - iss_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) 808 - { 809 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 810 - 811 - return vb2_dqbuf(&vfh->queue, b, file->f_flags & O_NONBLOCK); 812 - } 813 - 814 - /* 815 - * Stream management 816 - * 817 - * Every ISS pipeline has a single input and a single output. The input can be 818 - * either a sensor or a video node. The output is always a video node. 819 - * 820 - * As every pipeline has an output video node, the ISS video objects at the 821 - * pipeline output stores the pipeline state. It tracks the streaming state of 822 - * both the input and output, as well as the availability of buffers. 823 - * 824 - * In sensor-to-memory mode, frames are always available at the pipeline input. 825 - * Starting the sensor usually requires I2C transfers and must be done in 826 - * interruptible context. The pipeline is started and stopped synchronously 827 - * to the stream on/off commands. All modules in the pipeline will get their 828 - * subdev set stream handler called. The module at the end of the pipeline must 829 - * delay starting the hardware until buffers are available at its output. 830 - * 831 - * In memory-to-memory mode, starting/stopping the stream requires 832 - * synchronization between the input and output. ISS modules can't be stopped 833 - * in the middle of a frame, and at least some of the modules seem to become 834 - * busy as soon as they're started, even if they don't receive a frame start 835 - * event. For that reason frames need to be processed in single-shot mode. The 836 - * driver needs to wait until a frame is completely processed and written to 837 - * memory before restarting the pipeline for the next frame. Pipelined 838 - * processing might be possible but requires more testing. 839 - * 840 - * Stream start must be delayed until buffers are available at both the input 841 - * and output. The pipeline must be started in the vb2 queue callback with 842 - * the buffers queue spinlock held. The modules subdev set stream operation must 843 - * not sleep. 844 - */ 845 - static int 846 - iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) 847 - { 848 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 849 - struct iss_video *video = video_drvdata(file); 850 - struct media_device *mdev = video->video.entity.graph_obj.mdev; 851 - struct media_pipeline_pad_iter iter; 852 - enum iss_pipeline_state state; 853 - struct iss_pipeline *pipe; 854 - struct iss_video *far_end; 855 - struct media_pad *pad; 856 - unsigned long flags; 857 - int ret; 858 - 859 - if (type != video->type) 860 - return -EINVAL; 861 - 862 - mutex_lock(&video->stream_lock); 863 - 864 - /* 865 - * Start streaming on the pipeline. No link touching an entity in the 866 - * pipeline can be activated or deactivated once streaming is started. 867 - */ 868 - pipe = to_iss_pipeline(&video->video.entity) ? : &video->pipe; 869 - pipe->external = NULL; 870 - pipe->external_rate = 0; 871 - pipe->external_bpp = 0; 872 - 873 - ret = media_entity_enum_init(&pipe->ent_enum, mdev); 874 - if (ret) 875 - goto err_entity_enum_init; 876 - 877 - if (video->iss->pdata->set_constraints) 878 - video->iss->pdata->set_constraints(video->iss, true); 879 - 880 - ret = video_device_pipeline_start(&video->video, &pipe->pipe); 881 - if (ret < 0) 882 - goto err_media_pipeline_start; 883 - 884 - media_pipeline_for_each_pad(&pipe->pipe, &iter, pad) 885 - media_entity_enum_set(&pipe->ent_enum, pad->entity); 886 - 887 - /* 888 - * Verify that the currently configured format matches the output of 889 - * the connected subdev. 890 - */ 891 - ret = iss_video_check_format(video, vfh); 892 - if (ret < 0) 893 - goto err_iss_video_check_format; 894 - 895 - video->bpl_padding = ret; 896 - video->bpl_value = vfh->format.fmt.pix.bytesperline; 897 - 898 - /* 899 - * Find the ISS video node connected at the far end of the pipeline and 900 - * update the pipeline. 901 - */ 902 - far_end = iss_video_far_end(video, pipe); 903 - if (IS_ERR(far_end)) { 904 - ret = PTR_ERR(far_end); 905 - goto err_iss_video_check_format; 906 - } 907 - 908 - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 909 - state = ISS_PIPELINE_STREAM_OUTPUT | ISS_PIPELINE_IDLE_OUTPUT; 910 - pipe->input = far_end; 911 - pipe->output = video; 912 - } else { 913 - if (!far_end) { 914 - ret = -EPIPE; 915 - goto err_iss_video_check_format; 916 - } 917 - 918 - state = ISS_PIPELINE_STREAM_INPUT | ISS_PIPELINE_IDLE_INPUT; 919 - pipe->input = video; 920 - pipe->output = far_end; 921 - } 922 - 923 - spin_lock_irqsave(&pipe->lock, flags); 924 - pipe->state &= ~ISS_PIPELINE_STREAM; 925 - pipe->state |= state; 926 - spin_unlock_irqrestore(&pipe->lock, flags); 927 - 928 - /* 929 - * Set the maximum time per frame as the value requested by userspace. 930 - * This is a soft limit that can be overridden if the hardware doesn't 931 - * support the request limit. 932 - */ 933 - if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 934 - pipe->max_timeperframe = vfh->timeperframe; 935 - 936 - video->queue = &vfh->queue; 937 - INIT_LIST_HEAD(&video->dmaqueue); 938 - video->error = false; 939 - atomic_set(&pipe->frame_number, -1); 940 - 941 - ret = vb2_streamon(&vfh->queue, type); 942 - if (ret < 0) 943 - goto err_iss_video_check_format; 944 - 945 - /* 946 - * In sensor-to-memory mode, the stream can be started synchronously 947 - * to the stream on command. In memory-to-memory mode, it will be 948 - * started when buffers are queued on both the input and output. 949 - */ 950 - if (!pipe->input) { 951 - unsigned long flags; 952 - 953 - ret = omap4iss_pipeline_set_stream(pipe, 954 - ISS_PIPELINE_STREAM_CONTINUOUS); 955 - if (ret < 0) 956 - goto err_omap4iss_set_stream; 957 - spin_lock_irqsave(&video->qlock, flags); 958 - if (list_empty(&video->dmaqueue)) 959 - video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_UNDERRUN; 960 - spin_unlock_irqrestore(&video->qlock, flags); 961 - } 962 - 963 - mutex_unlock(&video->stream_lock); 964 - 965 - return 0; 966 - 967 - err_omap4iss_set_stream: 968 - vb2_streamoff(&vfh->queue, type); 969 - err_iss_video_check_format: 970 - video_device_pipeline_stop(&video->video); 971 - err_media_pipeline_start: 972 - if (video->iss->pdata->set_constraints) 973 - video->iss->pdata->set_constraints(video->iss, false); 974 - video->queue = NULL; 975 - 976 - err_entity_enum_init: 977 - media_entity_enum_cleanup(&pipe->ent_enum); 978 - 979 - mutex_unlock(&video->stream_lock); 980 - 981 - return ret; 982 - } 983 - 984 - static int 985 - iss_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) 986 - { 987 - struct iss_video_fh *vfh = to_iss_video_fh(fh); 988 - struct iss_video *video = video_drvdata(file); 989 - struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity); 990 - enum iss_pipeline_state state; 991 - unsigned long flags; 992 - 993 - if (type != video->type) 994 - return -EINVAL; 995 - 996 - mutex_lock(&video->stream_lock); 997 - 998 - if (!vb2_is_streaming(&vfh->queue)) 999 - goto done; 1000 - 1001 - /* Update the pipeline state. */ 1002 - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1003 - state = ISS_PIPELINE_STREAM_OUTPUT 1004 - | ISS_PIPELINE_QUEUE_OUTPUT; 1005 - else 1006 - state = ISS_PIPELINE_STREAM_INPUT 1007 - | ISS_PIPELINE_QUEUE_INPUT; 1008 - 1009 - spin_lock_irqsave(&pipe->lock, flags); 1010 - pipe->state &= ~state; 1011 - spin_unlock_irqrestore(&pipe->lock, flags); 1012 - 1013 - /* Stop the stream. */ 1014 - omap4iss_pipeline_set_stream(pipe, ISS_PIPELINE_STREAM_STOPPED); 1015 - vb2_streamoff(&vfh->queue, type); 1016 - video->queue = NULL; 1017 - 1018 - media_entity_enum_cleanup(&pipe->ent_enum); 1019 - 1020 - if (video->iss->pdata->set_constraints) 1021 - video->iss->pdata->set_constraints(video->iss, false); 1022 - video_device_pipeline_stop(&video->video); 1023 - 1024 - done: 1025 - mutex_unlock(&video->stream_lock); 1026 - return 0; 1027 - } 1028 - 1029 - static int 1030 - iss_video_enum_input(struct file *file, void *fh, struct v4l2_input *input) 1031 - { 1032 - if (input->index > 0) 1033 - return -EINVAL; 1034 - 1035 - strscpy(input->name, "camera", sizeof(input->name)); 1036 - input->type = V4L2_INPUT_TYPE_CAMERA; 1037 - 1038 - return 0; 1039 - } 1040 - 1041 - static int 1042 - iss_video_g_input(struct file *file, void *fh, unsigned int *input) 1043 - { 1044 - *input = 0; 1045 - 1046 - return 0; 1047 - } 1048 - 1049 - static int 1050 - iss_video_s_input(struct file *file, void *fh, unsigned int input) 1051 - { 1052 - return input == 0 ? 0 : -EINVAL; 1053 - } 1054 - 1055 - static const struct v4l2_ioctl_ops iss_video_ioctl_ops = { 1056 - .vidioc_querycap = iss_video_querycap, 1057 - .vidioc_enum_fmt_vid_cap = iss_video_enum_format, 1058 - .vidioc_g_fmt_vid_cap = iss_video_get_format, 1059 - .vidioc_s_fmt_vid_cap = iss_video_set_format, 1060 - .vidioc_try_fmt_vid_cap = iss_video_try_format, 1061 - .vidioc_g_fmt_vid_out = iss_video_get_format, 1062 - .vidioc_s_fmt_vid_out = iss_video_set_format, 1063 - .vidioc_try_fmt_vid_out = iss_video_try_format, 1064 - .vidioc_g_selection = iss_video_get_selection, 1065 - .vidioc_s_selection = iss_video_set_selection, 1066 - .vidioc_g_parm = iss_video_get_param, 1067 - .vidioc_s_parm = iss_video_set_param, 1068 - .vidioc_reqbufs = iss_video_reqbufs, 1069 - .vidioc_querybuf = iss_video_querybuf, 1070 - .vidioc_qbuf = iss_video_qbuf, 1071 - .vidioc_expbuf = iss_video_expbuf, 1072 - .vidioc_dqbuf = iss_video_dqbuf, 1073 - .vidioc_streamon = iss_video_streamon, 1074 - .vidioc_streamoff = iss_video_streamoff, 1075 - .vidioc_enum_input = iss_video_enum_input, 1076 - .vidioc_g_input = iss_video_g_input, 1077 - .vidioc_s_input = iss_video_s_input, 1078 - }; 1079 - 1080 - /* ----------------------------------------------------------------------------- 1081 - * V4L2 file operations 1082 - */ 1083 - 1084 - static int iss_video_open(struct file *file) 1085 - { 1086 - struct iss_video *video = video_drvdata(file); 1087 - struct iss_video_fh *handle; 1088 - struct vb2_queue *q; 1089 - int ret = 0; 1090 - 1091 - handle = kzalloc(sizeof(*handle), GFP_KERNEL); 1092 - if (!handle) 1093 - return -ENOMEM; 1094 - 1095 - v4l2_fh_init(&handle->vfh, &video->video); 1096 - v4l2_fh_add(&handle->vfh); 1097 - 1098 - /* If this is the first user, initialise the pipeline. */ 1099 - if (!omap4iss_get(video->iss)) { 1100 - ret = -EBUSY; 1101 - goto done; 1102 - } 1103 - 1104 - ret = v4l2_pipeline_pm_get(&video->video.entity); 1105 - if (ret < 0) { 1106 - omap4iss_put(video->iss); 1107 - goto done; 1108 - } 1109 - 1110 - q = &handle->queue; 1111 - 1112 - q->type = video->type; 1113 - q->io_modes = VB2_MMAP | VB2_DMABUF; 1114 - q->drv_priv = handle; 1115 - q->ops = &iss_video_vb2ops; 1116 - q->mem_ops = &vb2_dma_contig_memops; 1117 - q->buf_struct_size = sizeof(struct iss_buffer); 1118 - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 1119 - q->dev = video->iss->dev; 1120 - 1121 - ret = vb2_queue_init(q); 1122 - if (ret) { 1123 - omap4iss_put(video->iss); 1124 - goto done; 1125 - } 1126 - 1127 - memset(&handle->format, 0, sizeof(handle->format)); 1128 - handle->format.type = video->type; 1129 - handle->timeperframe.denominator = 1; 1130 - 1131 - handle->video = video; 1132 - file->private_data = &handle->vfh; 1133 - 1134 - done: 1135 - if (ret < 0) { 1136 - v4l2_fh_del(&handle->vfh); 1137 - v4l2_fh_exit(&handle->vfh); 1138 - kfree(handle); 1139 - } 1140 - 1141 - return ret; 1142 - } 1143 - 1144 - static int iss_video_release(struct file *file) 1145 - { 1146 - struct iss_video *video = video_drvdata(file); 1147 - struct v4l2_fh *vfh = file->private_data; 1148 - struct iss_video_fh *handle = to_iss_video_fh(vfh); 1149 - 1150 - /* Disable streaming and free the buffers queue resources. */ 1151 - iss_video_streamoff(file, vfh, video->type); 1152 - 1153 - v4l2_pipeline_pm_put(&video->video.entity); 1154 - 1155 - /* Release the videobuf2 queue */ 1156 - vb2_queue_release(&handle->queue); 1157 - 1158 - v4l2_fh_del(vfh); 1159 - v4l2_fh_exit(vfh); 1160 - kfree(handle); 1161 - file->private_data = NULL; 1162 - 1163 - omap4iss_put(video->iss); 1164 - 1165 - return 0; 1166 - } 1167 - 1168 - static __poll_t iss_video_poll(struct file *file, poll_table *wait) 1169 - { 1170 - struct iss_video_fh *vfh = to_iss_video_fh(file->private_data); 1171 - 1172 - return vb2_poll(&vfh->queue, file, wait); 1173 - } 1174 - 1175 - static int iss_video_mmap(struct file *file, struct vm_area_struct *vma) 1176 - { 1177 - struct iss_video_fh *vfh = to_iss_video_fh(file->private_data); 1178 - 1179 - return vb2_mmap(&vfh->queue, vma); 1180 - } 1181 - 1182 - static const struct v4l2_file_operations iss_video_fops = { 1183 - .owner = THIS_MODULE, 1184 - .unlocked_ioctl = video_ioctl2, 1185 - .open = iss_video_open, 1186 - .release = iss_video_release, 1187 - .poll = iss_video_poll, 1188 - .mmap = iss_video_mmap, 1189 - }; 1190 - 1191 - /* ----------------------------------------------------------------------------- 1192 - * ISS video core 1193 - */ 1194 - 1195 - static const struct iss_video_operations iss_video_dummy_ops = { 1196 - }; 1197 - 1198 - int omap4iss_video_init(struct iss_video *video, const char *name) 1199 - { 1200 - const char *direction; 1201 - int ret; 1202 - 1203 - switch (video->type) { 1204 - case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1205 - direction = "output"; 1206 - video->pad.flags = MEDIA_PAD_FL_SINK; 1207 - break; 1208 - case V4L2_BUF_TYPE_VIDEO_OUTPUT: 1209 - direction = "input"; 1210 - video->pad.flags = MEDIA_PAD_FL_SOURCE; 1211 - break; 1212 - 1213 - default: 1214 - return -EINVAL; 1215 - } 1216 - 1217 - ret = media_entity_pads_init(&video->video.entity, 1, &video->pad); 1218 - if (ret < 0) 1219 - return ret; 1220 - 1221 - spin_lock_init(&video->qlock); 1222 - mutex_init(&video->mutex); 1223 - atomic_set(&video->active, 0); 1224 - 1225 - spin_lock_init(&video->pipe.lock); 1226 - mutex_init(&video->stream_lock); 1227 - 1228 - /* Initialize the video device. */ 1229 - if (!video->ops) 1230 - video->ops = &iss_video_dummy_ops; 1231 - 1232 - video->video.fops = &iss_video_fops; 1233 - snprintf(video->video.name, sizeof(video->video.name), 1234 - "OMAP4 ISS %s %s", name, direction); 1235 - video->video.vfl_type = VFL_TYPE_VIDEO; 1236 - video->video.release = video_device_release_empty; 1237 - video->video.ioctl_ops = &iss_video_ioctl_ops; 1238 - video->pipe.stream_state = ISS_PIPELINE_STREAM_STOPPED; 1239 - 1240 - video_set_drvdata(&video->video, video); 1241 - 1242 - return 0; 1243 - } 1244 - 1245 - void omap4iss_video_cleanup(struct iss_video *video) 1246 - { 1247 - media_entity_cleanup(&video->video.entity); 1248 - mutex_destroy(&video->stream_lock); 1249 - mutex_destroy(&video->mutex); 1250 - } 1251 - 1252 - int omap4iss_video_register(struct iss_video *video, struct v4l2_device *vdev) 1253 - { 1254 - int ret; 1255 - 1256 - video->video.v4l2_dev = vdev; 1257 - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1258 - video->video.device_caps = V4L2_CAP_VIDEO_CAPTURE; 1259 - else 1260 - video->video.device_caps = V4L2_CAP_VIDEO_OUTPUT; 1261 - video->video.device_caps |= V4L2_CAP_STREAMING; 1262 - 1263 - ret = video_register_device(&video->video, VFL_TYPE_VIDEO, -1); 1264 - if (ret < 0) 1265 - dev_err(video->iss->dev, 1266 - "could not register video device (%d)\n", ret); 1267 - 1268 - return ret; 1269 - } 1270 - 1271 - void omap4iss_video_unregister(struct iss_video *video) 1272 - { 1273 - video_unregister_device(&video->video); 1274 - }
-203
drivers/staging/media/omap4iss/iss_video.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ */ 2 - /* 3 - * TI OMAP4 ISS V4L2 Driver - Generic video node 4 - * 5 - * Copyright (C) 2012 Texas Instruments, Inc. 6 - * 7 - * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 - */ 9 - 10 - #ifndef OMAP4_ISS_VIDEO_H 11 - #define OMAP4_ISS_VIDEO_H 12 - 13 - #include <linux/v4l2-mediabus.h> 14 - #include <media/media-entity.h> 15 - #include <media/v4l2-dev.h> 16 - #include <media/v4l2-fh.h> 17 - #include <media/videobuf2-v4l2.h> 18 - #include <media/videobuf2-dma-contig.h> 19 - 20 - #define ISS_VIDEO_DRIVER_NAME "issvideo" 21 - 22 - struct iss_device; 23 - struct iss_video; 24 - struct v4l2_mbus_framefmt; 25 - struct v4l2_pix_format; 26 - 27 - /* 28 - * struct iss_format_info - ISS media bus format information 29 - * @code: V4L2 media bus format code 30 - * @truncated: V4L2 media bus format code for the same format truncated to 10 31 - * bits. Identical to @code if the format is 10 bits wide or less. 32 - * @uncompressed: V4L2 media bus format code for the corresponding uncompressed 33 - * format. Identical to @code if the format is not DPCM compressed. 34 - * @flavor: V4L2 media bus format code for the same pixel layout but 35 - * shifted to be 8 bits per pixel. =0 if format is not shiftable. 36 - * @pixelformat: V4L2 pixel format FCC identifier 37 - * @bpp: Bits per pixel 38 - */ 39 - struct iss_format_info { 40 - u32 code; 41 - u32 truncated; 42 - u32 uncompressed; 43 - u32 flavor; 44 - u32 pixelformat; 45 - unsigned int bpp; 46 - }; 47 - 48 - enum iss_pipeline_stream_state { 49 - ISS_PIPELINE_STREAM_STOPPED = 0, 50 - ISS_PIPELINE_STREAM_CONTINUOUS = 1, 51 - ISS_PIPELINE_STREAM_SINGLESHOT = 2, 52 - }; 53 - 54 - enum iss_pipeline_state { 55 - /* The stream has been started on the input video node. */ 56 - ISS_PIPELINE_STREAM_INPUT = BIT(0), 57 - /* The stream has been started on the output video node. */ 58 - ISS_PIPELINE_STREAM_OUTPUT = BIT(1), 59 - /* At least one buffer is queued on the input video node. */ 60 - ISS_PIPELINE_QUEUE_INPUT = BIT(2), 61 - /* At least one buffer is queued on the output video node. */ 62 - ISS_PIPELINE_QUEUE_OUTPUT = BIT(3), 63 - /* The input entity is idle, ready to be started. */ 64 - ISS_PIPELINE_IDLE_INPUT = BIT(4), 65 - /* The output entity is idle, ready to be started. */ 66 - ISS_PIPELINE_IDLE_OUTPUT = BIT(5), 67 - /* The pipeline is currently streaming. */ 68 - ISS_PIPELINE_STREAM = BIT(6), 69 - }; 70 - 71 - /* 72 - * struct iss_pipeline - An OMAP4 ISS hardware pipeline 73 - * @ent_enum: Entities in the pipeline 74 - * @error: A hardware error occurred during capture 75 - */ 76 - struct iss_pipeline { 77 - struct media_pipeline pipe; 78 - spinlock_t lock; /* Pipeline state and queue flags */ 79 - unsigned int state; 80 - enum iss_pipeline_stream_state stream_state; 81 - struct iss_video *input; 82 - struct iss_video *output; 83 - struct media_entity_enum ent_enum; 84 - atomic_t frame_number; 85 - bool do_propagation; /* of frame number */ 86 - bool error; 87 - struct v4l2_fract max_timeperframe; 88 - struct v4l2_subdev *external; 89 - unsigned int external_rate; 90 - int external_bpp; 91 - }; 92 - 93 - static inline struct iss_pipeline *to_iss_pipeline(struct media_entity *entity) 94 - { 95 - struct media_pipeline *pipe = media_entity_pipeline(entity); 96 - 97 - if (!pipe) 98 - return NULL; 99 - 100 - return container_of(pipe, struct iss_pipeline, pipe); 101 - } 102 - 103 - static inline int iss_pipeline_ready(struct iss_pipeline *pipe) 104 - { 105 - return pipe->state == (ISS_PIPELINE_STREAM_INPUT | 106 - ISS_PIPELINE_STREAM_OUTPUT | 107 - ISS_PIPELINE_QUEUE_INPUT | 108 - ISS_PIPELINE_QUEUE_OUTPUT | 109 - ISS_PIPELINE_IDLE_INPUT | 110 - ISS_PIPELINE_IDLE_OUTPUT); 111 - } 112 - 113 - /* 114 - * struct iss_buffer - ISS buffer 115 - * @buffer: ISS video buffer 116 - * @iss_addr: Physical address of the buffer. 117 - */ 118 - struct iss_buffer { 119 - /* common v4l buffer stuff -- must be first */ 120 - struct vb2_v4l2_buffer vb; 121 - struct list_head list; 122 - dma_addr_t iss_addr; 123 - }; 124 - 125 - #define to_iss_buffer(buf) container_of(buf, struct iss_buffer, vb) 126 - 127 - enum iss_video_dmaqueue_flags { 128 - /* Set if DMA queue becomes empty when ISS_PIPELINE_STREAM_CONTINUOUS */ 129 - ISS_VIDEO_DMAQUEUE_UNDERRUN = BIT(0), 130 - /* Set when queuing buffer to an empty DMA queue */ 131 - ISS_VIDEO_DMAQUEUE_QUEUED = BIT(1), 132 - }; 133 - 134 - #define iss_video_dmaqueue_flags_clr(video) \ 135 - ({ (video)->dmaqueue_flags = 0; }) 136 - 137 - /* 138 - * struct iss_video_operations - ISS video operations 139 - * @queue: Resume streaming when a buffer is queued. Called on VIDIOC_QBUF 140 - * if there was no buffer previously queued. 141 - */ 142 - struct iss_video_operations { 143 - int (*queue)(struct iss_video *video, struct iss_buffer *buffer); 144 - }; 145 - 146 - struct iss_video { 147 - struct video_device video; 148 - enum v4l2_buf_type type; 149 - struct media_pad pad; 150 - 151 - struct mutex mutex; /* format and crop settings */ 152 - atomic_t active; 153 - 154 - struct iss_device *iss; 155 - 156 - unsigned int capture_mem; 157 - unsigned int bpl_alignment; /* alignment value */ 158 - unsigned int bpl_zero_padding; /* whether the alignment is optional */ 159 - unsigned int bpl_max; /* maximum bytes per line value */ 160 - unsigned int bpl_value; /* bytes per line value */ 161 - unsigned int bpl_padding; /* padding at end of line */ 162 - 163 - /* Pipeline state */ 164 - struct iss_pipeline pipe; 165 - struct mutex stream_lock; /* pipeline and stream states */ 166 - bool error; 167 - 168 - /* Video buffers queue */ 169 - struct vb2_queue *queue; 170 - spinlock_t qlock; /* protects dmaqueue and error */ 171 - struct list_head dmaqueue; 172 - enum iss_video_dmaqueue_flags dmaqueue_flags; 173 - 174 - const struct iss_video_operations *ops; 175 - }; 176 - 177 - #define to_iss_video(vdev) container_of(vdev, struct iss_video, video) 178 - 179 - struct iss_video_fh { 180 - struct v4l2_fh vfh; 181 - struct iss_video *video; 182 - struct vb2_queue queue; 183 - struct v4l2_format format; 184 - struct v4l2_fract timeperframe; 185 - }; 186 - 187 - #define to_iss_video_fh(fh) container_of(fh, struct iss_video_fh, vfh) 188 - #define iss_video_queue_to_iss_video_fh(q) \ 189 - container_of(q, struct iss_video_fh, queue) 190 - 191 - int omap4iss_video_init(struct iss_video *video, const char *name); 192 - void omap4iss_video_cleanup(struct iss_video *video); 193 - int omap4iss_video_register(struct iss_video *video, 194 - struct v4l2_device *vdev); 195 - void omap4iss_video_unregister(struct iss_video *video); 196 - struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video); 197 - void omap4iss_video_cancel_stream(struct iss_video *video); 198 - struct media_pad *omap4iss_video_remote_pad(struct iss_video *video); 199 - 200 - const struct iss_format_info * 201 - omap4iss_video_format_info(u32 code); 202 - 203 - #endif /* OMAP4_ISS_VIDEO_H */
-66
include/linux/platform_data/media/omap4iss.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef ARCH_ARM_PLAT_OMAP4_ISS_H 3 - #define ARCH_ARM_PLAT_OMAP4_ISS_H 4 - 5 - #include <linux/i2c.h> 6 - 7 - struct iss_device; 8 - 9 - enum iss_interface_type { 10 - ISS_INTERFACE_CSI2A_PHY1, 11 - ISS_INTERFACE_CSI2B_PHY2, 12 - }; 13 - 14 - /** 15 - * struct iss_csiphy_lane: CSI2 lane position and polarity 16 - * @pos: position of the lane 17 - * @pol: polarity of the lane 18 - */ 19 - struct iss_csiphy_lane { 20 - u8 pos; 21 - u8 pol; 22 - }; 23 - 24 - #define ISS_CSIPHY1_NUM_DATA_LANES 4 25 - #define ISS_CSIPHY2_NUM_DATA_LANES 1 26 - 27 - /** 28 - * struct iss_csiphy_lanes_cfg - CSI2 lane configuration 29 - * @data: Configuration of one or two data lanes 30 - * @clk: Clock lane configuration 31 - */ 32 - struct iss_csiphy_lanes_cfg { 33 - struct iss_csiphy_lane data[ISS_CSIPHY1_NUM_DATA_LANES]; 34 - struct iss_csiphy_lane clk; 35 - }; 36 - 37 - /** 38 - * struct iss_csi2_platform_data - CSI2 interface platform data 39 - * @crc: Enable the cyclic redundancy check 40 - * @vpclk_div: Video port output clock control 41 - */ 42 - struct iss_csi2_platform_data { 43 - unsigned crc:1; 44 - unsigned vpclk_div:2; 45 - struct iss_csiphy_lanes_cfg lanecfg; 46 - }; 47 - 48 - struct iss_subdev_i2c_board_info { 49 - struct i2c_board_info *board_info; 50 - int i2c_adapter_id; 51 - }; 52 - 53 - struct iss_v4l2_subdevs_group { 54 - struct iss_subdev_i2c_board_info *subdevs; 55 - enum iss_interface_type interface; 56 - union { 57 - struct iss_csi2_platform_data csi2; 58 - } bus; /* gcc < 4.6.0 chokes on anonymous union initializers */ 59 - }; 60 - 61 - struct iss_platform_data { 62 - struct iss_v4l2_subdevs_group *subdevs; 63 - void (*set_constraints)(struct iss_device *iss, bool enable); 64 - }; 65 - 66 - #endif