13bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski/* 23bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * V4L2 Driver for PXA camera host 33bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * 43bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * Copyright (C) 2006, Sascha Hauer, Pengutronix 53bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> 63bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * 73bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * This program is free software; you can redistribute it and/or modify 83bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * it under the terms of the GNU General Public License as published by 93bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * the Free Software Foundation; either version 2 of the License, or 103bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * (at your option) any later version. 113bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski */ 123bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/init.h> 143bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/module.h> 157102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#include <linux/io.h> 163bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/delay.h> 173bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/dma-mapping.h> 183bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/errno.h> 193bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/fs.h> 203bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/interrupt.h> 213bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/kernel.h> 223bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/mm.h> 233bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/moduleparam.h> 243bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/time.h> 253bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/device.h> 263bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/platform_device.h> 273bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/clk.h> 28d514edac5df2149207f1ae2f52de63882c692eecJonathan Cameron#include <linux/sched.h> 295a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <media/v4l2-common.h> 323bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <media/v4l2-dev.h> 33092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas#include <media/videobuf-dma-sg.h> 343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <media/soc_camera.h> 35760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski#include <media/soc_mediabus.h> 363bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/videodev2.h> 383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 39cfbaf4dfe765ae33e1a26b3eb0eda64ff00fc481Eric Miao#include <mach/dma.h> 40a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/camera.h> 413bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 4264dc3c1a906467d90c24913b0b38dd13d9378f4fMauro Carvalho Chehab#define PXA_CAM_VERSION "0.0.6" 433bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#define PXA_CAM_DRV_NAME "pxa27x-camera" 443bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 455ca11fa3e0025864df930d6d97470b87c35919edEric Miao/* Camera Interface */ 465ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0 0x0000 475ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1 0x0004 485ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2 0x0008 495ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3 0x000C 505ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4 0x0010 515ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR 0x0014 525ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR 0x0018 535ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CITOR 0x001C 545ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIBR0 0x0028 555ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIBR1 0x0030 565ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIBR2 0x0038 575ca11fa3e0025864df930d6d97470b87c35919edEric Miao 585ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_DMAEN (1 << 31) /* DMA request enable */ 595ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_PAR_EN (1 << 30) /* Parity enable */ 605ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_SL_CAP_EN (1 << 29) /* Capture enable for slave mode */ 615ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_ENB (1 << 28) /* Camera interface enable */ 625ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_DIS (1 << 27) /* Camera interface disable */ 635ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */ 645ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_TOM (1 << 9) /* Time-out mask */ 655ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */ 665ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_FEM (1 << 7) /* FIFO-empty mask */ 675ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_EOLM (1 << 6) /* End-of-line mask */ 685ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_PERRM (1 << 5) /* Parity-error mask */ 695ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_QDM (1 << 4) /* Quick-disable mask */ 705ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_CDM (1 << 3) /* Disable-done mask */ 715ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_SOFM (1 << 2) /* Start-of-frame mask */ 725ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_EOFM (1 << 1) /* End-of-frame mask */ 735ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_FOM (1 << 0) /* FIFO-overrun mask */ 745ca11fa3e0025864df930d6d97470b87c35919edEric Miao 755ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_TBIT (1 << 31) /* Transparency bit */ 765ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */ 775ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */ 785ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */ 795ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_RGB_F (1 << 11) /* RGB format */ 805ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_YCBCR_F (1 << 10) /* YCbCr format */ 815ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_RGB_BPP (0x7 << 7) /* RGB bis per pixel mask */ 825ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_RAW_BPP (0x3 << 5) /* Raw bis per pixel mask */ 835ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_COLOR_SP (0x3 << 3) /* Color space mask */ 845ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_DW (0x7 << 0) /* Data width mask */ 855ca11fa3e0025864df930d6d97470b87c35919edEric Miao 865ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2_BLW (0xff << 24) /* Beginning-of-line pixel clock 875ca11fa3e0025864df930d6d97470b87c35919edEric Miao wait count mask */ 885ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2_ELW (0xff << 16) /* End-of-line pixel clock 895ca11fa3e0025864df930d6d97470b87c35919edEric Miao wait count mask */ 905ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2_HSW (0x3f << 10) /* Horizontal sync pulse width mask */ 915ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock 925ca11fa3e0025864df930d6d97470b87c35919edEric Miao wait count mask */ 935ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2_FSW (0x7 << 0) /* Frame stabilization 945ca11fa3e0025864df930d6d97470b87c35919edEric Miao wait count mask */ 955ca11fa3e0025864df930d6d97470b87c35919edEric Miao 965ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3_BFW (0xff << 24) /* Beginning-of-frame line clock 975ca11fa3e0025864df930d6d97470b87c35919edEric Miao wait count mask */ 985ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3_EFW (0xff << 16) /* End-of-frame line clock 995ca11fa3e0025864df930d6d97470b87c35919edEric Miao wait count mask */ 1005ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3_VSW (0x3f << 10) /* Vertical sync pulse width mask */ 1015ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock 1025ca11fa3e0025864df930d6d97470b87c35919edEric Miao wait count mask */ 1035ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3_LPF (0x7ff << 0) /* Lines per frame mask */ 1045ca11fa3e0025864df930d6d97470b87c35919edEric Miao 1055ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_MCLK_DLY (0x3 << 24) /* MCLK Data Capture Delay mask */ 1065ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_PCLK_EN (1 << 23) /* Pixel clock enable */ 1075ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_PCP (1 << 22) /* Pixel clock polarity */ 1085ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_HSP (1 << 21) /* Horizontal sync polarity */ 1095ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_VSP (1 << 20) /* Vertical sync polarity */ 1105ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_MCLK_EN (1 << 19) /* MCLK enable */ 1115ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */ 1125ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_DIV (0xff << 0) /* Clock divisor mask */ 1135ca11fa3e0025864df930d6d97470b87c35919edEric Miao 1145ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_FTO (1 << 15) /* FIFO time-out */ 1155ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */ 1165ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */ 1175ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_RDAV_0 (1 << 12) /* Channel 0 receive data available */ 1185ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_FEMPTY_2 (1 << 11) /* Channel 2 FIFO empty */ 1195ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_FEMPTY_1 (1 << 10) /* Channel 1 FIFO empty */ 1205ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_FEMPTY_0 (1 << 9) /* Channel 0 FIFO empty */ 1215ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_EOL (1 << 8) /* End of line */ 1225ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_PAR_ERR (1 << 7) /* Parity error */ 1235ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_CQD (1 << 6) /* Camera interface quick disable */ 1245ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_CDD (1 << 5) /* Camera interface disable done */ 1255ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_SOF (1 << 4) /* Start of frame */ 1265ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_EOF (1 << 3) /* End of frame */ 1275ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_IFO_2 (1 << 2) /* FIFO overrun for Channel 2 */ 1285ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_IFO_1 (1 << 1) /* FIFO overrun for Channel 1 */ 1295ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_IFO_0 (1 << 0) /* FIFO overrun for Channel 0 */ 1305ca11fa3e0025864df930d6d97470b87c35919edEric Miao 1315ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FLVL2 (0x7f << 23) /* FIFO 2 level mask */ 1325ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FLVL1 (0x7f << 16) /* FIFO 1 level mask */ 1335ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FLVL0 (0xff << 8) /* FIFO 0 level mask */ 1345ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_THL_0 (0x3 << 4) /* Threshold Level for Channel 0 FIFO */ 1355ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_RESET_F (1 << 3) /* Reset input FIFOs */ 1365ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FEN2 (1 << 2) /* FIFO enable for channel 2 */ 1375ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FEN1 (1 << 1) /* FIFO enable for channel 1 */ 1385ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FEN0 (1 << 0) /* FIFO enable for channel 0 */ 1395ca11fa3e0025864df930d6d97470b87c35919edEric Miao 1407102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR0_SIM_MP (0 << 24) 1417102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR0_SIM_SP (1 << 24) 1427102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR0_SIM_MS (2 << 24) 1437102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR0_SIM_EP (3 << 24) 1447102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR0_SIM_ES (4 << 24) 1457102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski 1467102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR1_DW_VAL(x) ((x) & CICR1_DW) /* Data bus width */ 1477102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR1_PPL_VAL(x) (((x) << 15) & CICR1_PPL) /* Pixels per line */ 148a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport#define CICR1_COLOR_SP_VAL(x) (((x) << 3) & CICR1_COLOR_SP) /* color space */ 149a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport#define CICR1_RGB_BPP_VAL(x) (((x) << 7) & CICR1_RGB_BPP) /* bpp for rgb */ 150a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport#define CICR1_RGBT_CONV_VAL(x) (((x) << 29) & CICR1_RGBT_CONV) /* rgbt conv */ 1517102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski 1527102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR2_BLW_VAL(x) (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */ 1537102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR2_ELW_VAL(x) (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */ 1547102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR2_HSW_VAL(x) (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */ 1557102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */ 1567102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR2_FSW_VAL(x) (((x) << 0) & CICR2_FSW) /* Frame stabilization wait count */ 1577102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski 1587102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR3_BFW_VAL(x) (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count */ 1597102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR3_EFW_VAL(x) (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */ 1607102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR3_VSW_VAL(x) (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */ 1617102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR3_LPF_VAL(x) (((x) << 0) & CICR3_LPF) /* Lines per frame */ 1627102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski 1633bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#define CICR0_IRQ_MASK (CICR0_TOM | CICR0_RDAVM | CICR0_FEM | CICR0_EOLM | \ 1643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \ 1653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski CICR0_EOFM | CICR0_FOM) 1663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 1673bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski/* 1683bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * Structures 1693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski */ 170a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportenum pxa_camera_active_dma { 171a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport DMA_Y = 0x1, 172a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport DMA_U = 0x2, 173a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport DMA_V = 0x4, 174a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport}; 175a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 176a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport/* descriptor needed for the PXA DMA engine */ 177a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstruct pxa_cam_dma { 178a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport dma_addr_t sg_dma; 179a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport struct pxa_dma_desc *sg_cpu; 180a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport size_t sg_size; 181a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport int sglen; 182a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport}; 1833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 1843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski/* buffer for one video frame */ 1853bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistruct pxa_buffer { 1863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski /* common v4l buffer stuff -- must be first */ 187760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski struct videobuf_buffer vb; 188760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski enum v4l2_mbus_pixelcode code; 189a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport /* our descriptor lists for Y, U and V channels */ 190760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski struct pxa_cam_dma dmas[3]; 191760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski int inwork; 192760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski enum pxa_camera_active_dma active_dma; 1933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}; 1943bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 1953bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistruct pxa_camera_dev { 196eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski struct soc_camera_host soc_host; 1975d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski /* 1985d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * PXA27x is only supposed to handle one camera on its Quick Capture 1993bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * interface. If anyone ever builds hardware to enable more than 2005d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * one camera, they will have to modify this driver too 2015d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski */ 2023bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct soc_camera_device *icd; 2033bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct clk *clk; 2043bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2053bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski unsigned int irq; 2063bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski void __iomem *base; 207a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 208e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski int channels; 209a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport unsigned int dma_chans[3]; 2103bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2113bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxacamera_platform_data *pdata; 2123bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct resource *res; 2133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski unsigned long platform_flags; 214cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski unsigned long ciclk; 215cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski unsigned long mclk; 216cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski u32 mclk_divisor; 217679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski u16 width_flags; /* max 10 bits */ 2183bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2193bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct list_head capture; 2203bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2213bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski spinlock_t lock; 2223bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2233bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_buffer *active; 2245aa2110f3f33feb4a0c67a4996dc400dc594bc1dGuennadi Liakhovetski struct pxa_dma_desc *sg_tail[3]; 2253f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 2263f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik u32 save_cicr[5]; 2273bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}; 2283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2296a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetskistruct pxa_cam { 2306a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski unsigned long flags; 2316a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski}; 2326a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 2333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic const char *pxa_cam_driver_description = "PXA_Camera"; 2343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2353bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic unsigned int vid_limit = 16; /* Video memory limit, in Mb */ 2363bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski/* 2383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * Videobuf operations 2393bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski */ 2407102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, 2417102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski unsigned int *size) 2423bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 2433bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct soc_camera_device *icd = vq->priv_data; 244760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, 245760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski icd->current_fmt->host_fmt); 246760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski 247760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (bytes_per_line < 0) 248760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski return bytes_per_line; 2493bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2507dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size); 2513bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 252760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski *size = bytes_per_line * icd->user_height; 2533bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2543bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (0 == *count) 2553bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski *count = 32; 256dab7e3106ddd6cbc3b55301228407b9d17ce7773Andreas Bombe if (*size * *count > vid_limit * 1024 * 1024) 257dab7e3106ddd6cbc3b55301228407b9d17ce7773Andreas Bombe *count = (vid_limit * 1024 * 1024) / *size; 2583bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2593bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return 0; 2603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 2613bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2623bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) 2633bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 2643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct soc_camera_device *icd = vq->priv_data; 2657dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 2663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); 267a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport int i; 2683bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski BUG_ON(in_interrupt()); 2703bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2717dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, 2723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski &buf->vb, buf->vb.baddr, buf->vb.bsize); 2733bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2745d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski /* 2755d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * This waits until this buffer is out of danger, i.e., until it is no 2765d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * longer in STATE_QUEUED or STATE_ACTIVE 2775d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski */ 2780e0809a58869e3e422985f868ad5e0da1fc0ba85Hans Verkuil videobuf_waiton(vq, &buf->vb, 0, 0); 279952684035a91334dbe33b15063514cab5e7c6907Laurent Pinchart videobuf_dma_unmap(vq->dev, dma); 2803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski videobuf_dma_free(dma); 2813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 282a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { 283a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport if (buf->dmas[i].sg_cpu) 28496c75399544838e1752001c8abdde36dd459cf8fGuennadi Liakhovetski dma_free_coherent(ici->v4l2_dev.dev, 28596c75399544838e1752001c8abdde36dd459cf8fGuennadi Liakhovetski buf->dmas[i].sg_size, 286a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport buf->dmas[i].sg_cpu, 287a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport buf->dmas[i].sg_dma); 288a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport buf->dmas[i].sg_cpu = NULL; 289a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport } 2903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 2913bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski buf->vb.state = VIDEOBUF_NEEDS_INIT; 2923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 2933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 29437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmikstatic int calculate_dma_sglen(struct scatterlist *sglist, int sglen, 29537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik int sg_first_ofs, int size) 29637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik{ 29737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik int i, offset, dma_len, xfer_len; 29837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik struct scatterlist *sg; 29937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 30037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik offset = sg_first_ofs; 30137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik for_each_sg(sglist, sg, sglen, i) { 30237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik dma_len = sg_dma_len(sg); 30337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 30437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */ 30537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik xfer_len = roundup(min(dma_len - offset, size), 8); 30637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 30737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik size = max(0, size - xfer_len); 30837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik offset = 0; 30937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik if (size == 0) 31037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik break; 31137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik } 31237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 31337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik BUG_ON(size != 0); 31437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik return i + 1; 31537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik} 31637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 31737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik/** 31837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * pxa_init_dma_channel - init dma descriptors 31937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @pcdev: pxa camera device 32037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @buf: pxa buffer to find pxa dma channel 32137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @dma: dma video buffer 32237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @channel: dma channel (0 => 'Y', 1 => 'U', 2 => 'V') 32337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @cibr: camera Receive Buffer Register 32437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @size: bytes to transfer 32537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @sg_first: first element of sg_list 32637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @sg_first_ofs: offset in first element of sg_list 32737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * 32837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * Prepares the pxa dma descriptors to transfer one camera channel. 32937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * Beware sg_first and sg_first_ofs are both input and output parameters. 33037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * 33137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * Returns 0 or -ENOMEM if no coherent memory is available 33237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik */ 333a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, 334a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport struct pxa_buffer *buf, 335a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport struct videobuf_dmabuf *dma, int channel, 33637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik int cibr, int size, 33737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik struct scatterlist **sg_first, int *sg_first_ofs) 338a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport{ 339a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport struct pxa_cam_dma *pxa_dma = &buf->dmas[channel]; 340979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski struct device *dev = pcdev->soc_host.v4l2_dev.dev; 34137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik struct scatterlist *sg; 34237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik int i, offset, sglen; 34337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik int dma_len = 0, xfer_len = 0; 344a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 345a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport if (pxa_dma->sg_cpu) 346979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dma_free_coherent(dev, pxa_dma->sg_size, 347a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_dma->sg_cpu, pxa_dma->sg_dma); 348a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 34937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik sglen = calculate_dma_sglen(*sg_first, dma->sglen, 35037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik *sg_first_ofs, size); 35137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 352a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc); 353979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski pxa_dma->sg_cpu = dma_alloc_coherent(dev, pxa_dma->sg_size, 354a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport &pxa_dma->sg_dma, GFP_KERNEL); 355a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport if (!pxa_dma->sg_cpu) 356a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport return -ENOMEM; 357a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 358a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_dma->sglen = sglen; 35937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik offset = *sg_first_ofs; 360a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 361979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_dbg(dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", 36237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik *sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma); 363a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 36437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 36537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik for_each_sg(*sg_first, sg, sglen, i) { 36637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik dma_len = sg_dma_len(sg); 367a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 368a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */ 36937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik xfer_len = roundup(min(dma_len - offset, size), 8); 370a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 37137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik size = max(0, size - xfer_len); 37237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 37337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr; 37437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik pxa_dma->sg_cpu[i].dtadr = sg_dma_address(sg) + offset; 375a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_dma->sg_cpu[i].dcmd = 376a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len; 377256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik#ifdef DEBUG 378256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik if (!i) 379256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_dma->sg_cpu[i].dcmd |= DCMD_STARTIRQEN; 380256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik#endif 381a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_dma->sg_cpu[i].ddadr = 382a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc); 38337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 384979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_vdbg(dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", 38537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc), 38637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik sg_dma_address(sg) + offset, xfer_len); 38737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik offset = 0; 38837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 38937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik if (size == 0) 39037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik break; 391a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport } 392a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 393256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_dma->sg_cpu[sglen].ddadr = DDADR_STOP; 394256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_dma->sg_cpu[sglen].dcmd = DCMD_FLOWSRC | DCMD_BURST8 | DCMD_ENDIRQEN; 395a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 39637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik /* 39737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * Handle 1 special case : 39837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * - in 3 planes (YUV422P format), we might finish with xfer_len equal 39937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * to dma_len (end on PAGE boundary). In this case, the sg element 40037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * for next plane should be the next after the last used to store the 40137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * last scatter gather RAM page 40237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik */ 40337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik if (xfer_len >= dma_len) { 40437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik *sg_first_ofs = xfer_len - dma_len; 40537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik *sg_first = sg_next(sg); 40637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik } else { 40737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik *sg_first_ofs = xfer_len; 40837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik *sg_first = sg; 40937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik } 41037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 411a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport return 0; 412a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport} 413a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 414256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_videobuf_set_actdma(struct pxa_camera_dev *pcdev, 415256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik struct pxa_buffer *buf) 416256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{ 417256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik buf->active_dma = DMA_Y; 418256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik if (pcdev->channels == 3) 419256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik buf->active_dma |= DMA_U | DMA_V; 420256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik} 421256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 422256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik/* 423256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Please check the DMA prepared buffer structure in : 424256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Documentation/video4linux/pxa_camera.txt 425256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Please check also in pxa_camera_check_link_miss() to understand why DMA chain 426256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * modification while DMA chain is running will work anyway. 427256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik */ 4287102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic int pxa_videobuf_prepare(struct videobuf_queue *vq, 4297102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski struct videobuf_buffer *vb, enum v4l2_field field) 4303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 4313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct soc_camera_device *icd = vq->priv_data; 4327dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 4333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_camera_dev *pcdev = ici->priv; 434979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski struct device *dev = pcdev->soc_host.v4l2_dev.dev; 4353bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); 436a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport int ret; 437a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport int size_y, size_u = 0, size_v = 0; 438760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, 439760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski icd->current_fmt->host_fmt); 440760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski 441760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (bytes_per_line < 0) 442760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski return bytes_per_line; 4433bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 444979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, 4453bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski vb, vb->baddr, vb->bsize); 4463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 4473bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski /* Added list head initialization on alloc */ 4483bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski WARN_ON(!list_empty(&vb->queue)); 4493bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 4503bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#ifdef DEBUG 4515d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski /* 4525d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * This can be useful if you want to see if we actually fill 4535d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * the buffer with something 4545d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski */ 4553bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski memset((void *)vb->baddr, 0xaa, vb->bsize); 4563bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#endif 4573bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 4583bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski BUG_ON(NULL == icd->current_fmt); 4593bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 4605d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski /* 4615d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * I think, in buf_prepare you only have to protect global data, 4625d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * the actual buffer is yours 4635d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski */ 4643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski buf->inwork = 1; 4653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 466760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (buf->code != icd->current_fmt->code || 4676a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski vb->width != icd->user_width || 4686a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski vb->height != icd->user_height || 4693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski vb->field != field) { 470760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski buf->code = icd->current_fmt->code; 4716a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski vb->width = icd->user_width; 4726a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski vb->height = icd->user_height; 4733bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski vb->field = field; 4743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski vb->state = VIDEOBUF_NEEDS_INIT; 4753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 4763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 477760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski vb->size = bytes_per_line * vb->height; 4783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (0 != vb->baddr && vb->bsize < vb->size) { 4793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski ret = -EINVAL; 4803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto out; 4813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 4823bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 4833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (vb->state == VIDEOBUF_NEEDS_INIT) { 48437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik int size = vb->size; 48537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik int next_ofs = 0; 4863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct videobuf_dmabuf *dma = videobuf_to_dma(vb); 48737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik struct scatterlist *sg; 4883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 4893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski ret = videobuf_iolock(vq, vb, NULL); 4903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (ret) 4913bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto fail; 4923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 4935aa2110f3f33feb4a0c67a4996dc400dc594bc1dGuennadi Liakhovetski if (pcdev->channels == 3) { 494a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport size_y = size / 2; 495a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport size_u = size_v = size / 4; 496a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport } else { 497a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport size_y = size; 498a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport } 499a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 50037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik sg = dma->sglist; 5013bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 50237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik /* init DMA for Y channel */ 50337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y, 50437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik &sg, &next_ofs); 505a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport if (ret) { 506979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_err(dev, "DMA initialization for Y/RGB failed\n"); 5073bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto fail; 5083bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 5093bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 51037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik /* init DMA for U channel */ 51137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik if (size_u) 51237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1, 51337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik size_u, &sg, &next_ofs); 51437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik if (ret) { 515979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_err(dev, "DMA initialization for U failed\n"); 51637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik goto fail_u; 51737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik } 51837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik 51937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik /* init DMA for V channel */ 52037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik if (size_v) 52137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2, 52237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik size_v, &sg, &next_ofs); 52337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik if (ret) { 524979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_err(dev, "DMA initialization for V failed\n"); 52537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik goto fail_v; 5263bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 5273bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 5283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski vb->state = VIDEOBUF_PREPARED; 5293bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 5303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 5313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski buf->inwork = 0; 532256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_videobuf_set_actdma(pcdev, buf); 5333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 5343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return 0; 5353bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 536a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportfail_v: 537979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dma_free_coherent(dev, buf->dmas[1].sg_size, 538a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma); 539a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportfail_u: 540979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dma_free_coherent(dev, buf->dmas[0].sg_size, 541a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma); 5423bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskifail: 5433bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski free_buffer(vq, buf); 5443bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiout: 5453bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski buf->inwork = 0; 5463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return ret; 5473bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 5483bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 549256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik/** 550256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * pxa_dma_start_channels - start DMA channel for active buffer 551256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * @pcdev: pxa camera device 552256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * 553256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Initialize DMA channels to the beginning of the active video buffer, and 554256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * start these channels. 555256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik */ 556256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_dma_start_channels(struct pxa_camera_dev *pcdev) 557256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{ 558256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik int i; 559256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik struct pxa_buffer *active; 560256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 561256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik active = pcdev->active; 562256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 563256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik for (i = 0; i < pcdev->channels; i++) { 5640166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_dbg(pcdev->soc_host.v4l2_dev.dev, 5650166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski "%s (channel=%d) ddadr=%08x\n", __func__, 566256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik i, active->dmas[i].sg_dma); 567256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma; 568256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik DCSR(pcdev->dma_chans[i]) = DCSR_RUN; 569256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik } 570256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik} 571256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 572256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev) 573256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{ 574256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik int i; 575256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 576256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik for (i = 0; i < pcdev->channels; i++) { 5770166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_dbg(pcdev->soc_host.v4l2_dev.dev, 5780166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski "%s (channel=%d)\n", __func__, i); 579256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik DCSR(pcdev->dma_chans[i]) = 0; 580256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik } 581256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik} 582256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 583256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev, 584256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik struct pxa_buffer *buf) 585256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{ 586256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik int i; 587256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik struct pxa_dma_desc *buf_last_desc; 588256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 589256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik for (i = 0; i < pcdev->channels; i++) { 590256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik buf_last_desc = buf->dmas[i].sg_cpu + buf->dmas[i].sglen; 591256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik buf_last_desc->ddadr = DDADR_STOP; 592256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 593ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski if (pcdev->sg_tail[i]) 594ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski /* Link the new buffer to the old tail */ 595ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski pcdev->sg_tail[i]->ddadr = buf->dmas[i].sg_dma; 596256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 597ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski /* Update the channel tail */ 598ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski pcdev->sg_tail[i] = buf_last_desc; 599ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski } 600256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik} 601256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 602256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik/** 603256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * pxa_camera_start_capture - start video capturing 604256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * @pcdev: camera device 605256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * 606256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Launch capturing. DMA channels should not be active yet. They should get 607256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * activated at the end of frame interrupt, to capture only whole frames, and 608256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * never begin the capture of a partial frame. 609256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik */ 610256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_camera_start_capture(struct pxa_camera_dev *pcdev) 611256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{ 612a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier unsigned long cicr0; 613256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 614979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); 615256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik /* Enable End-Of-Frame Interrupt */ 616256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB; 617256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik cicr0 &= ~CICR0_EOFM; 618256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik __raw_writel(cicr0, pcdev->base + CICR0); 619256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik} 620256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 621256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev) 622256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{ 623256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik unsigned long cicr0; 624256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 625256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_dma_stop_channels(pcdev); 626256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 627256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB; 628256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik __raw_writel(cicr0, pcdev->base + CICR0); 629256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 6308c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik pcdev->active = NULL; 631979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); 632256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik} 633256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 6342dd54a54c19d0e5b50f4e1c591653772ead9d4a1Guennadi Liakhovetski/* Called under spinlock_irqsave(&pcdev->lock, ...) */ 6357102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic void pxa_videobuf_queue(struct videobuf_queue *vq, 6367102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski struct videobuf_buffer *vb) 6373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 6383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct soc_camera_device *icd = vq->priv_data; 6397dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 6403bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_camera_dev *pcdev = ici->priv; 6413bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); 6423bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 6437dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d active=%p\n", 6440166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski __func__, vb, vb->baddr, vb->bsize, pcdev->active); 645256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 6463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski list_add_tail(&vb->queue, &pcdev->capture); 6473bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 6483bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski vb->state = VIDEOBUF_ACTIVE; 649256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_dma_add_tail_buf(pcdev, buf); 6503bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 651256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik if (!pcdev->active) 652256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_camera_start_capture(pcdev); 6533bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 6543bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 6553bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic void pxa_videobuf_release(struct videobuf_queue *vq, 6563bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct videobuf_buffer *vb) 6573bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 6583bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); 6593bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#ifdef DEBUG 6603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct soc_camera_device *icd = vq->priv_data; 6617dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct device *dev = icd->parent; 6623bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 6630166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, 6643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski vb, vb->baddr, vb->bsize); 6653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 6663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski switch (vb->state) { 6673bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski case VIDEOBUF_ACTIVE: 6680166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_dbg(dev, "%s (active)\n", __func__); 6693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski break; 6703bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski case VIDEOBUF_QUEUED: 6710166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_dbg(dev, "%s (queued)\n", __func__); 6723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski break; 6733bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski case VIDEOBUF_PREPARED: 6740166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_dbg(dev, "%s (prepared)\n", __func__); 6753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski break; 6763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski default: 6770166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_dbg(dev, "%s (unknown)\n", __func__); 6783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski break; 6793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 6803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#endif 6813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 6823bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski free_buffer(vq, buf); 6833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 6843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 685a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, 686a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport struct videobuf_buffer *vb, 687a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport struct pxa_buffer *buf) 688a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport{ 689256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik int i; 6905ca11fa3e0025864df930d6d97470b87c35919edEric Miao 691a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ 692a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport list_del_init(&vb->queue); 693a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport vb->state = VIDEOBUF_DONE; 694a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport do_gettimeofday(&vb->ts); 695a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport vb->field_count++; 696a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport wake_up(&vb->done); 697979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s dequeud buffer (vb=0x%p)\n", 698979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski __func__, vb); 699a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 700a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport if (list_empty(&pcdev->capture)) { 701256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_camera_stop_capture(pcdev); 702256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik for (i = 0; i < pcdev->channels; i++) 703256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pcdev->sg_tail[i] = NULL; 704a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport return; 705a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport } 706a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 707a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pcdev->active = list_entry(pcdev->capture.next, 708a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport struct pxa_buffer, vb.queue); 709a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport} 710a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 711256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik/** 712256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * pxa_camera_check_link_miss - check missed DMA linking 713256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * @pcdev: camera device 714256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * 715256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * The DMA chaining is done with DMA running. This means a tiny temporal window 716256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * remains, where a buffer is queued on the chain, while the chain is already 71725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * stopped. This means the tailed buffer would never be transferred by DMA. 718256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * This function restarts the capture for this corner case, where : 719256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * - DADR() == DADDR_STOP 720256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * - a videobuffer is queued on the pcdev->capture list 721256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * 722256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Please check the "DMA hot chaining timeslice issue" in 723256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Documentation/video4linux/pxa_camera.txt 724256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * 725256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Context: should only be called within the dma irq handler 726256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik */ 727256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev) 728256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{ 729256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik int i, is_dma_stopped = 1; 730256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 731256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik for (i = 0; i < pcdev->channels; i++) 732256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP) 733256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik is_dma_stopped = 0; 734979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_dbg(pcdev->soc_host.v4l2_dev.dev, 735979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski "%s : top queued buffer=%p, dma_stopped=%d\n", 736256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik __func__, pcdev->active, is_dma_stopped); 737256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik if (pcdev->active && is_dma_stopped) 738256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_camera_start_capture(pcdev); 739256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik} 740256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 741a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, 742a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport enum pxa_camera_active_dma act_dma) 7433bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 744979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski struct device *dev = pcdev->soc_host.v4l2_dev.dev; 7453bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_buffer *buf; 7463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski unsigned long flags; 747e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski u32 status, camera_status, overrun; 7483bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct videobuf_buffer *vb; 7493bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 7503bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski spin_lock_irqsave(&pcdev->lock, flags); 7513bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 752a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport status = DCSR(channel); 753256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik DCSR(channel) = status; 754256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 755256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik camera_status = __raw_readl(pcdev->base + CISR); 756256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik overrun = CISR_IFO_0; 757256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik if (pcdev->channels == 3) 758256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik overrun |= CISR_IFO_1 | CISR_IFO_2; 7597102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski 7603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (status & DCSR_BUSERR) { 761979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_err(dev, "DMA Bus Error IRQ!\n"); 7623bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto out; 7633bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 7643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 765256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) { 766979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_err(dev, "Unknown DMA IRQ source, status: 0x%08x\n", 767979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski status); 7683bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto out; 7693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 7703bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 7718c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik /* 7728c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * pcdev->active should not be NULL in DMA irq handler. 7738c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * 7748c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * But there is one corner case : if capture was stopped due to an 7758c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * overrun of channel 1, and at that same channel 2 was completed. 7768c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * 7778c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * When handling the overrun in DMA irq for channel 1, we'll stop the 7788c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * capture and restart it (and thus set pcdev->active to NULL). But the 7798c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * DMA irq handler will already be pending for channel 2. So on entering 7808c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * the DMA irq handler for channel 2 there will be no active buffer, yet 7818c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * that is normal. 7828c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik */ 7838c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik if (!pcdev->active) 7843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto out; 7853bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 7863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski vb = &pcdev->active->vb; 7873bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski buf = container_of(vb, struct pxa_buffer, vb); 7883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski WARN_ON(buf->inwork || list_empty(&vb->queue)); 7893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 790979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_dbg(dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", 791256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik __func__, channel, status & DCSR_STARTINTR ? "SOF " : "", 792256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel)); 793256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 794256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik if (status & DCSR_ENDINTR) { 7958c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik /* 7968c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * It's normal if the last frame creates an overrun, as there 7978c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik * are no more DMA descriptors to fetch from QCI fifos 7988c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik */ 7998c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik if (camera_status & overrun && 8008c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik !list_is_last(pcdev->capture.next, &pcdev->capture)) { 801979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_dbg(dev, "FIFO overrun! CISR: %x\n", 802256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik camera_status); 803256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_camera_stop_capture(pcdev); 804256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_camera_start_capture(pcdev); 805256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik goto out; 806256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik } 807256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik buf->active_dma &= ~act_dma; 808256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik if (!buf->active_dma) { 809256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_camera_wakeup(pcdev, vb, buf); 810256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_camera_check_link_miss(pcdev); 811256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik } 812256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik } 8133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 8143bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiout: 8153bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski spin_unlock_irqrestore(&pcdev->lock, flags); 8163bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 8173bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 818a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic void pxa_camera_dma_irq_y(int channel, void *data) 819a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport{ 820a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport struct pxa_camera_dev *pcdev = data; 821a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_camera_dma_irq(channel, pcdev, DMA_Y); 822a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport} 823a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 824a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic void pxa_camera_dma_irq_u(int channel, void *data) 825a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport{ 826a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport struct pxa_camera_dev *pcdev = data; 827a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_camera_dma_irq(channel, pcdev, DMA_U); 828a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport} 829a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 830a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic void pxa_camera_dma_irq_v(int channel, void *data) 831a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport{ 832a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport struct pxa_camera_dev *pcdev = data; 833a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_camera_dma_irq(channel, pcdev, DMA_V); 834a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport} 835a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 8367102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic struct videobuf_queue_ops pxa_videobuf_ops = { 8373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski .buf_setup = pxa_videobuf_setup, 8383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski .buf_prepare = pxa_videobuf_prepare, 8393bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski .buf_queue = pxa_videobuf_queue, 8403bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski .buf_release = pxa_videobuf_release, 8413bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}; 8423bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 843a034d1b76b173b37f9a3646aa8f50a2c14a0f3eaMagnus Dammstatic void pxa_camera_init_videobuf(struct videobuf_queue *q, 844092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas struct soc_camera_device *icd) 845092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas{ 8467dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 847a034d1b76b173b37f9a3646aa8f50a2c14a0f3eaMagnus Damm struct pxa_camera_dev *pcdev = ici->priv; 848a034d1b76b173b37f9a3646aa8f50a2c14a0f3eaMagnus Damm 8495d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski /* 8505d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * We must pass NULL as dev pointer, then all pci_* dma operations 8515d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * transform to normal dma_* ones. 8525d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski */ 853a034d1b76b173b37f9a3646aa8f50a2c14a0f3eaMagnus Damm videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock, 854092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, 855b6a633c18ba83c0c8e96759a31d356bfb77e2b5fGuennadi Liakhovetski sizeof(struct pxa_buffer), icd, &icd->video_lock); 856092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas} 857092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas 85840e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetskistatic u32 mclk_get_divisor(struct platform_device *pdev, 85940e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski struct pxa_camera_dev *pcdev) 8603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 861cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski unsigned long mclk = pcdev->mclk; 8626a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski struct device *dev = &pdev->dev; 863cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski u32 div; 8643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski unsigned long lcdclk; 8653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 866cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski lcdclk = clk_get_rate(pcdev->clk); 867cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski pcdev->ciclk = lcdclk; 8683bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 869cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski /* mclk <= ciclk / 4 (27.4.2) */ 870cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski if (mclk > lcdclk / 4) { 871cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski mclk = lcdclk / 4; 872979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_warn(dev, "Limiting master clock to %lu\n", mclk); 873cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski } 874cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski 875cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */ 876cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; 8773bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 878cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski /* If we're not supplying MCLK, leave it at 0 */ 879cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) 880cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski pcdev->mclk = lcdclk / (2 * (div + 1)); 8813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 882979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski dev_dbg(dev, "LCD clock %luHz, target freq %luHz, divisor %u\n", 88340e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski lcdclk, mclk, div); 8843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 8853bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return div; 8863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 8873bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 888cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetskistatic void recalculate_fifo_timeout(struct pxa_camera_dev *pcdev, 889cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski unsigned long pclk) 890cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski{ 891cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski /* We want a timeout > 1 pixel time, not ">=" */ 892cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski u32 ciclk_per_pixel = pcdev->ciclk / pclk + 1; 893cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski 894cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski __raw_writel(ciclk_per_pixel, pcdev->base + CITOR); 895cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski} 896cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski 8977102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic void pxa_camera_activate(struct pxa_camera_dev *pcdev) 8983bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 8993bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski u32 cicr4 = 0; 9003bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9015ca11fa3e0025864df930d6d97470b87c35919edEric Miao /* disable all interrupts */ 9025ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(0x3ff, pcdev->base + CICR0); 9033bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9043bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) 9053bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cicr4 |= CICR4_PCLK_EN; 9063bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) 9073bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cicr4 |= CICR4_MCLK_EN; 9083bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_PCP) 9093bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cicr4 |= CICR4_PCP; 9103bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_HSP) 9113bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cicr4 |= CICR4_HSP; 9123bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_VSP) 9133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cicr4 |= CICR4_VSP; 9143bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 915cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski __raw_writel(pcdev->mclk_divisor | cicr4, pcdev->base + CICR4); 916cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski 917cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) 918cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski /* Initialise the timeout under the assumption pclk = mclk */ 919cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski recalculate_fifo_timeout(pcdev, pcdev->mclk); 920cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski else 921cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski /* "Safe default" - 13MHz */ 922cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski recalculate_fifo_timeout(pcdev, 13000000); 9233bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 92491acd962301af86d5af02ddefdb8147322a0b9b0Philipp Zabel clk_prepare_enable(pcdev->clk); 9253bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 9263bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9277102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) 9283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 92991acd962301af86d5af02ddefdb8147322a0b9b0Philipp Zabel clk_disable_unprepare(pcdev->clk); 9303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 9313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9323bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic irqreturn_t pxa_camera_irq(int irq, void *data) 9333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 9343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_camera_dev *pcdev = data; 935a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier unsigned long status, cifr, cicr0; 936256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik struct pxa_buffer *buf; 937256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik struct videobuf_buffer *vb; 9383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9395ca11fa3e0025864df930d6d97470b87c35919edEric Miao status = __raw_readl(pcdev->base + CISR); 9400166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_dbg(pcdev->soc_host.v4l2_dev.dev, 9410166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski "Camera interrupt status 0x%lx\n", status); 9423bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 943e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski if (!status) 944e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski return IRQ_NONE; 945e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski 9465ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(status, pcdev->base + CISR); 947e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski 948e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski if (status & CISR_EOF) { 949a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier /* Reset the FIFOs */ 950a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; 951a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier __raw_writel(cifr, pcdev->base + CIFR); 952a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier 953256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pcdev->active = list_first_entry(&pcdev->capture, 954256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik struct pxa_buffer, vb.queue); 955256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik vb = &pcdev->active->vb; 956256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik buf = container_of(vb, struct pxa_buffer, vb); 957256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_videobuf_set_actdma(pcdev, buf); 958256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 959256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_dma_start_channels(pcdev); 960256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik 9615ca11fa3e0025864df930d6d97470b87c35919edEric Miao cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_EOFM; 9625ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(cicr0, pcdev->base + CICR0); 963e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski } 964e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski 9653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return IRQ_HANDLED; 9663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 9673bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9681c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski/* 9691c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski * The following two functions absolutely depend on the fact, that 9701c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski * there can be only one camera on PXA quick capture interface 9711c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski * Called with .video_lock held 9721c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski */ 9737102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic int pxa_camera_add_device(struct soc_camera_device *icd) 9743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 9757dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 9763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_camera_dev *pcdev = ici->priv; 9773bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 978979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski if (pcdev->icd) 979979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski return -EBUSY; 9803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9817102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski pxa_camera_activate(pcdev); 98240e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski 98340e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski pcdev->icd = icd; 9843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9857dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_info(icd->parent, "PXA Camera driver attached to camera %d\n", 98640e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski icd->devnum); 9873bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 98840e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski return 0; 9893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 9903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9911c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski/* Called with .video_lock held */ 9927102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic void pxa_camera_remove_device(struct soc_camera_device *icd) 9933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 9947dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 9953bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_camera_dev *pcdev = ici->priv; 9963bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9973bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski BUG_ON(icd != pcdev->icd); 9983bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 9997dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_info(icd->parent, "PXA Camera driver detached from camera %d\n", 10003bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski icd->devnum); 10013bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 10023bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski /* disable capture, disable interrupts */ 10035ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(0x3ff, pcdev->base + CICR0); 1004a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 10053bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski /* Stop DMA engine */ 1006a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport DCSR(pcdev->dma_chans[0]) = 0; 1007a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport DCSR(pcdev->dma_chans[1]) = 0; 1008a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport DCSR(pcdev->dma_chans[2]) = 0; 10093bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 10107102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski pxa_camera_deactivate(pcdev); 10113bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 10123bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski pcdev->icd = NULL; 10133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 10143bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 1015ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetskistatic int test_platform_param(struct pxa_camera_dev *pcdev, 1016ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski unsigned char buswidth, unsigned long *flags) 10173bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 1018ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski /* 1019ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski * Platform specified synchronization and pixel clock polarities are 1020ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski * only a recommendation and are only used during probing. The PXA270 1021ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski * quick capture interface supports both. 1022ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski */ 1023ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ? 1024679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) | 1025679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski V4L2_MBUS_HSYNC_ACTIVE_HIGH | 1026679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski V4L2_MBUS_HSYNC_ACTIVE_LOW | 1027679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski V4L2_MBUS_VSYNC_ACTIVE_HIGH | 1028679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski V4L2_MBUS_VSYNC_ACTIVE_LOW | 1029679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski V4L2_MBUS_DATA_ACTIVE_HIGH | 1030679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski V4L2_MBUS_PCLK_SAMPLE_RISING | 1031679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski V4L2_MBUS_PCLK_SAMPLE_FALLING; 10323bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 10333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski /* If requested data width is supported by the platform, use it */ 1034679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if ((1 << (buswidth - 1)) & pcdev->width_flags) 1035679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski return 0; 1036ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski 1037679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski return -EINVAL; 1038ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski} 1039ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski 10406a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetskistatic void pxa_camera_setup_cicr(struct soc_camera_device *icd, 10416a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski unsigned long flags, __u32 pixfmt) 1042ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski{ 10437dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 1044ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski struct pxa_camera_dev *pcdev = ici->priv; 1045325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 10466a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski unsigned long dw, bpp; 1047325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0, y_skip_top; 1048325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski int ret = v4l2_subdev_call(sd, sensor, g_skip_top_lines, &y_skip_top); 1049325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski 1050325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski if (ret < 0) 1051325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski y_skip_top = 0; 10523bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 10535d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski /* 10545d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * Datawidth is now guaranteed to be equal to one of the three values. 10555d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * We fix bit-per-pixel equal to data-width... 10565d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski */ 1057679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski switch (icd->current_fmt->host_fmt->bits_per_sample) { 1058679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski case 10: 10593bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski dw = 4; 10603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski bpp = 0x40; 10613bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski break; 1062679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski case 9: 10633bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski dw = 3; 10643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski bpp = 0x20; 10653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski break; 10663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski default: 10675d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski /* 10685d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * Actually it can only be 8 now, 10695d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * default is just to silence compiler warnings 10705d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski */ 1071679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski case 8: 10723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski dw = 2; 10733bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski bpp = 0; 10743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 10753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 10763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) 10773bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cicr4 |= CICR4_PCLK_EN; 10783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) 10793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cicr4 |= CICR4_MCLK_EN; 1080679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) 10813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cicr4 |= CICR4_PCP; 1082679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) 10833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cicr4 |= CICR4_HSP; 1084679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) 10853bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cicr4 |= CICR4_VSP; 10863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 10875ca11fa3e0025864df930d6d97470b87c35919edEric Miao cicr0 = __raw_readl(pcdev->base + CICR0); 10883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (cicr0 & CICR0_ENB) 10895ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(cicr0 & ~CICR0_ENB, pcdev->base + CICR0); 1090a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 10916a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski cicr1 = CICR1_PPL_VAL(icd->user_width - 1) | bpp | dw; 1092a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 1093a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport switch (pixfmt) { 1094a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport case V4L2_PIX_FMT_YUV422P: 1095e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski pcdev->channels = 3; 1096a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport cicr1 |= CICR1_YCBCR_F; 10972a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik /* 10982a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik * Normally, pxa bus wants as input UYVY format. We allow all 10992a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik * reorderings of the YUV422 format, as no processing is done, 11002a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik * and the YUV stream is just passed through without any 11012a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik * transformation. Note that UYVY is the only format that 11022a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik * should be used if pxa framebuffer Overlay2 is used. 11032a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik */ 11042a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik case V4L2_PIX_FMT_UYVY: 11052a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik case V4L2_PIX_FMT_VYUY: 1106a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport case V4L2_PIX_FMT_YUYV: 11072a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik case V4L2_PIX_FMT_YVYU: 1108a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport cicr1 |= CICR1_COLOR_SP_VAL(2); 1109a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport break; 1110a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport case V4L2_PIX_FMT_RGB555: 1111a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport cicr1 |= CICR1_RGB_BPP_VAL(1) | CICR1_RGBT_CONV_VAL(2) | 1112a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport CICR1_TBIT | CICR1_COLOR_SP_VAL(1); 1113a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport break; 1114a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport case V4L2_PIX_FMT_RGB565: 1115a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport cicr1 |= CICR1_COLOR_SP_VAL(1) | CICR1_RGB_BPP_VAL(2); 1116a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport break; 1117a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport } 1118a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 11195ca11fa3e0025864df930d6d97470b87c35919edEric Miao cicr2 = 0; 11206a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski cicr3 = CICR3_LPF_VAL(icd->user_height - 1) | 1121325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski CICR3_BFW_VAL(min((u32)255, y_skip_top)); 1122cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski cicr4 |= pcdev->mclk_divisor; 11235ca11fa3e0025864df930d6d97470b87c35919edEric Miao 11245ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(cicr1, pcdev->base + CICR1); 11255ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(cicr2, pcdev->base + CICR2); 11265ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(cicr3, pcdev->base + CICR3); 11275ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(cicr4, pcdev->base + CICR4); 11283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 11293bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski /* CIF interrupts are not used, only DMA */ 11305ca11fa3e0025864df930d6d97470b87c35919edEric Miao cicr0 = (cicr0 & CICR0_ENB) | (pcdev->platform_flags & PXA_CAMERA_MASTER ? 11315ca11fa3e0025864df930d6d97470b87c35919edEric Miao CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)); 11325ca11fa3e0025864df930d6d97470b87c35919edEric Miao cicr0 |= CICR0_DMAEN | CICR0_IRQ_MASK; 11335ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(cicr0, pcdev->base + CICR0); 11346a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski} 11356a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 11368843d119eaf1a7a87a2cf8c3eadbd1937b16bc27Guennadi Liakhovetskistatic int pxa_camera_set_bus_param(struct soc_camera_device *icd) 11376a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski{ 1138679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 11397dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 11406a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski struct pxa_camera_dev *pcdev = ici->priv; 1141679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; 11428843d119eaf1a7a87a2cf8c3eadbd1937b16bc27Guennadi Liakhovetski u32 pixfmt = icd->current_fmt->host_fmt->fourcc; 1143679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski unsigned long bus_flags, common_flags; 1144760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski int ret; 11456a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski struct pxa_cam *cam = icd->host_priv; 11466a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1147d2dcad49bc346054b49bd40fd96f397fec695a0fGuennadi Liakhovetski ret = test_platform_param(pcdev, icd->current_fmt->host_fmt->bits_per_sample, 1148d2dcad49bc346054b49bd40fd96f397fec695a0fGuennadi Liakhovetski &bus_flags); 11496a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski if (ret < 0) 11506a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski return ret; 11516a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1152679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); 1153679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (!ret) { 1154679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski common_flags = soc_mbus_config_compatible(&cfg, 1155679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski bus_flags); 1156679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (!common_flags) { 1157679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski dev_warn(icd->parent, 1158679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski "Flags incompatible: camera 0x%x, host 0x%lx\n", 1159679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski cfg.flags, bus_flags); 1160679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski return -EINVAL; 1161679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski } 1162679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski } else if (ret != -ENOIOCTLCMD) { 1163679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski return ret; 1164679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski } else { 1165679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski common_flags = bus_flags; 1166679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski } 11676a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 11686a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski pcdev->channels = 1; 11696a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 11706a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski /* Make choises, based on platform preferences */ 1171679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && 1172679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { 11736a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_HSP) 1174679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; 11756a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski else 1176679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; 11776a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski } 11786a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1179679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && 1180679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { 11816a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_VSP) 1182679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; 11836a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski else 1184679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; 11856a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski } 11866a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1187679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && 1188679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { 11896a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_PCP) 1190679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; 11916a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski else 1192679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; 11936a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski } 11946a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1195679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski cfg.flags = common_flags; 1196679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); 1197679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (ret < 0 && ret != -ENOIOCTLCMD) { 1198679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n", 1199679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski common_flags, ret); 12006a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski return ret; 1201679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski } 1202679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski 1203679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski cam->flags = common_flags; 12046a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 12056a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski pxa_camera_setup_cicr(icd, common_flags, pixfmt); 12063bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 12073bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return 0; 12083bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 12093bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 12102a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmikstatic int pxa_camera_try_bus_param(struct soc_camera_device *icd, 12112a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik unsigned char buswidth) 1212ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski{ 1213679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 12147dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 1215ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski struct pxa_camera_dev *pcdev = ici->priv; 1216679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; 1217679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski unsigned long bus_flags, common_flags; 12182a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik int ret = test_platform_param(pcdev, buswidth, &bus_flags); 1219ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski 1220ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski if (ret < 0) 1221ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski return ret; 1222ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski 1223679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); 1224679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (!ret) { 1225679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski common_flags = soc_mbus_config_compatible(&cfg, 1226679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski bus_flags); 1227679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (!common_flags) { 1228679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski dev_warn(icd->parent, 1229679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski "Flags incompatible: camera 0x%x, host 0x%lx\n", 1230679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski cfg.flags, bus_flags); 1231679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski return -EINVAL; 1232679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski } 1233679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski } else if (ret == -ENOIOCTLCMD) { 1234679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski ret = 0; 1235679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski } 1236ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski 1237679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski return ret; 1238ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski} 1239ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski 1240760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetskistatic const struct soc_mbus_pixelfmt pxa_camera_formats[] = { 12412a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik { 1242760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski .fourcc = V4L2_PIX_FMT_YUV422P, 1243760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski .name = "Planar YUV422 16 bit", 1244760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski .bits_per_sample = 8, 1245760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski .packing = SOC_MBUS_PACKING_2X8_PADHI, 1246760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski .order = SOC_MBUS_ORDER_LE, 12472a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik }, 12482a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik}; 12492a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik 1250760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski/* This will be corrected as we get more formats */ 1251760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetskistatic bool pxa_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) 1252ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski{ 1253760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski return fmt->packing == SOC_MBUS_PACKING_NONE || 1254760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski (fmt->bits_per_sample == 8 && 1255760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || 1256760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski (fmt->bits_per_sample > 8 && 1257760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski fmt->packing == SOC_MBUS_PACKING_EXTEND16); 12582a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik} 12592a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik 12603805f201934e5384f6e941222dc1968cb638a88cHans Verkuilstatic int pxa_camera_get_formats(struct soc_camera_device *icd, unsigned int idx, 12612a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik struct soc_camera_format_xlate *xlate) 12622a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik{ 1263760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 12647dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct device *dev = icd->parent; 1265760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski int formats = 0, ret; 12666a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski struct pxa_cam *cam; 1267760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski enum v4l2_mbus_pixelcode code; 1268760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski const struct soc_mbus_pixelfmt *fmt; 12692a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik 1270760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); 1271760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (ret < 0) 1272760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski /* No more formats */ 1273760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski return 0; 12742a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik 1275760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski fmt = soc_mbus_get_fmtdesc(code); 1276760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (!fmt) { 12773805f201934e5384f6e941222dc1968cb638a88cHans Verkuil dev_err(dev, "Invalid format code #%u: %d\n", idx, code); 12782a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik return 0; 1279760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski } 12803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 1281760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski /* This also checks support for the requested bits-per-sample */ 1282760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski ret = pxa_camera_try_bus_param(icd, fmt->bits_per_sample); 12832a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik if (ret < 0) 12842a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik return 0; 12852a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik 12866a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski if (!icd->host_priv) { 12876a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski cam = kzalloc(sizeof(*cam), GFP_KERNEL); 12886a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski if (!cam) 12896a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski return -ENOMEM; 12906a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 12916a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski icd->host_priv = cam; 12926a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski } else { 12936a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski cam = icd->host_priv; 12946a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski } 12956a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1296760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski switch (code) { 1297ace6e9799f585994c92ac3c0696bc336e50077e6Guennadi Liakhovetski case V4L2_MBUS_FMT_UYVY8_2X8: 12982a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik formats++; 12992a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik if (xlate) { 1300760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski xlate->host_fmt = &pxa_camera_formats[0]; 1301760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski xlate->code = code; 13022a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik xlate++; 1303760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski dev_dbg(dev, "Providing format %s using code %d\n", 1304760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski pxa_camera_formats[0].name, code); 13052a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik } 1306ace6e9799f585994c92ac3c0696bc336e50077e6Guennadi Liakhovetski case V4L2_MBUS_FMT_VYUY8_2X8: 1307ace6e9799f585994c92ac3c0696bc336e50077e6Guennadi Liakhovetski case V4L2_MBUS_FMT_YUYV8_2X8: 1308ace6e9799f585994c92ac3c0696bc336e50077e6Guennadi Liakhovetski case V4L2_MBUS_FMT_YVYU8_2X8: 1309760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski case V4L2_MBUS_FMT_RGB565_2X8_LE: 1310760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: 1311760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (xlate) 13120166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_dbg(dev, "Providing format %s packed\n", 1313760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski fmt->name); 13142a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik break; 13152a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik default: 1316760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (!pxa_camera_packing_supported(fmt)) 1317760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski return 0; 1318760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (xlate) 13190166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_dbg(dev, 13202a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik "Providing format %s in pass-through mode\n", 1321760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski fmt->name); 1322760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski } 1323760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski 1324760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski /* Generic pass-through */ 1325760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski formats++; 1326760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (xlate) { 1327760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski xlate->host_fmt = fmt; 1328760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski xlate->code = code; 1329760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski xlate++; 13302a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik } 13312a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik 13322a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik return formats; 13332a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik} 13342a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik 13356a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetskistatic void pxa_camera_put_formats(struct soc_camera_device *icd) 13366a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski{ 13376a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski kfree(icd->host_priv); 13386a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski icd->host_priv = NULL; 13396a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski} 13406a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1341760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetskistatic int pxa_camera_check_frame(u32 width, u32 height) 13426a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski{ 13436a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski /* limit to pxa hardware capabilities */ 1344760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski return height < 32 || height > 2048 || width < 48 || width > 2048 || 1345760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski (width & 0x01); 13466a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski} 13476a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 134809e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetskistatic int pxa_camera_set_crop(struct soc_camera_device *icd, 134908590b9613f7f624fe3a052586eea2dbb3584b38Guennadi Liakhovetski struct v4l2_crop *a) 135009e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski{ 135108590b9613f7f624fe3a052586eea2dbb3584b38Guennadi Liakhovetski struct v4l2_rect *rect = &a->c; 13527dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct device *dev = icd->parent; 13537dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(dev); 135409e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski struct pxa_camera_dev *pcdev = ici->priv; 1355c9c1f1c0dbe90b82939917fdc3e4c9ccad42342dGuennadi Liakhovetski struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 135609e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski struct soc_camera_sense sense = { 135709e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski .master_clock = pcdev->mclk, 135809e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski .pixel_clock_max = pcdev->ciclk / 4, 135909e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski }; 1360760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski struct v4l2_mbus_framefmt mf; 13616a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski struct pxa_cam *cam = icd->host_priv; 1362760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski u32 fourcc = icd->current_fmt->host_fmt->fourcc; 136309e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski int ret; 136409e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski 136509e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski /* If PCLK is used to latch data from the sensor, check sense */ 136609e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) 136709e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski icd->sense = &sense; 136809e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski 136908590b9613f7f624fe3a052586eea2dbb3584b38Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, s_crop, a); 137009e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski 137109e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski icd->sense = NULL; 137209e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski 137309e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski if (ret < 0) { 13740166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_warn(dev, "Failed to crop to %ux%u@%u:%u\n", 137509e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski rect->width, rect->height, rect->left, rect->top); 13766a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski return ret; 13776a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski } 13786a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1379760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); 13806a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski if (ret < 0) 13816a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski return ret; 13826a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1383760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (pxa_camera_check_frame(mf.width, mf.height)) { 13846a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski /* 13856a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski * Camera cropping produced a frame beyond our capabilities. 13866a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski * FIXME: just extract a subframe, that we can process. 13876a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski */ 1388760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski v4l_bound_align_image(&mf.width, 48, 2048, 1, 1389760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski &mf.height, 32, 2048, 0, 1390760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); 1391760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); 13926a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski if (ret < 0) 13936a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski return ret; 13946a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1395760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (pxa_camera_check_frame(mf.width, mf.height)) { 13967dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_warn(icd->parent, 13976a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski "Inconsistent state. Use S_FMT to repair\n"); 13986a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski return -EINVAL; 13996a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski } 14006a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski } 14016a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 14026a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { 140309e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski if (sense.pixel_clock > sense.pixel_clock_max) { 14040166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_err(dev, 140509e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski "pixel clock %lu set by the camera too high!", 140609e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski sense.pixel_clock); 140709e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski return -EIO; 140809e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski } 140909e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski recalculate_fifo_timeout(pcdev, sense.pixel_clock); 141009e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski } 141109e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski 1412760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski icd->user_width = mf.width; 1413760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski icd->user_height = mf.height; 14146a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 1415760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski pxa_camera_setup_cicr(icd, cam->flags, fourcc); 14166a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski 141709e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski return ret; 141809e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski} 141909e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski 1420d8fac217c58f0101a351b9c8c80f1665bd9efef9Guennadi Liakhovetskistatic int pxa_camera_set_fmt(struct soc_camera_device *icd, 142109e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski struct v4l2_format *f) 1422ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski{ 14237dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct device *dev = icd->parent; 14247dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(dev); 1425cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski struct pxa_camera_dev *pcdev = ici->priv; 1426c9c1f1c0dbe90b82939917fdc3e4c9ccad42342dGuennadi Liakhovetski struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 14270ad675eb4533402fd7b03b25d1d4a0ab7a43ae6dGuennadi Liakhovetski const struct soc_camera_format_xlate *xlate = NULL; 1428cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski struct soc_camera_sense sense = { 1429cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski .master_clock = pcdev->mclk, 1430cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski .pixel_clock_max = pcdev->ciclk / 4, 1431cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski }; 143209e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski struct v4l2_pix_format *pix = &f->fmt.pix; 1433760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski struct v4l2_mbus_framefmt mf; 14340ad675eb4533402fd7b03b25d1d4a0ab7a43ae6dGuennadi Liakhovetski int ret; 143525c4d74ea6f07f2aaa3df537619680ba967043f5Guennadi Liakhovetski 143609e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); 143709e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski if (!xlate) { 14380166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_warn(dev, "Format %x not found\n", pix->pixelformat); 143909e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski return -EINVAL; 14400ad675eb4533402fd7b03b25d1d4a0ab7a43ae6dGuennadi Liakhovetski } 14412a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik 1442cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski /* If PCLK is used to latch data from the sensor, check sense */ 1443cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) 1444760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski /* The caller holds a mutex. */ 1445cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski icd->sense = &sense; 1446cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski 1447760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.width = pix->width; 1448760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.height = pix->height; 1449760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.field = pix->field; 1450760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.colorspace = pix->colorspace; 1451760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.code = xlate->code; 1452760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski 1453760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); 1454760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski 1455760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (mf.code != xlate->code) 1456760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski return -EINVAL; 14572a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik 1458cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski icd->sense = NULL; 1459cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski 1460cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski if (ret < 0) { 14610166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_warn(dev, "Failed to configure for format %x\n", 146209e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski pix->pixelformat); 1463760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski } else if (pxa_camera_check_frame(mf.width, mf.height)) { 14646a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski dev_warn(dev, 14656a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski "Camera driver produced an unsupported frame %dx%d\n", 1466760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.width, mf.height); 14676a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski ret = -EINVAL; 1468cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { 1469cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski if (sense.pixel_clock > sense.pixel_clock_max) { 14700166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski dev_err(dev, 1471cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski "pixel clock %lu set by the camera too high!", 1472cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski sense.pixel_clock); 1473cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski return -EIO; 1474cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski } 1475cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski recalculate_fifo_timeout(pcdev, sense.pixel_clock); 1476cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski } 14772a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik 1478760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (ret < 0) 1479760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski return ret; 1480760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski 1481760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski pix->width = mf.width; 1482760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski pix->height = mf.height; 1483760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski pix->field = mf.field; 1484760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski pix->colorspace = mf.colorspace; 1485760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski icd->current_fmt = xlate; 148625c4d74ea6f07f2aaa3df537619680ba967043f5Guennadi Liakhovetski 148725c4d74ea6f07f2aaa3df537619680ba967043f5Guennadi Liakhovetski return ret; 1488ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski} 1489ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski 1490d8fac217c58f0101a351b9c8c80f1665bd9efef9Guennadi Liakhovetskistatic int pxa_camera_try_fmt(struct soc_camera_device *icd, 1491d8fac217c58f0101a351b9c8c80f1665bd9efef9Guennadi Liakhovetski struct v4l2_format *f) 14923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 1493c9c1f1c0dbe90b82939917fdc3e4c9ccad42342dGuennadi Liakhovetski struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 14942a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik const struct soc_camera_format_xlate *xlate; 14952a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik struct v4l2_pix_format *pix = &f->fmt.pix; 1496760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski struct v4l2_mbus_framefmt mf; 14972a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik __u32 pixfmt = pix->pixelformat; 1498bf507158eb27ea94aca300b28ecee60fdbb40007Guennadi Liakhovetski int ret; 1499a2c8c68cca3dbb0c87f5034ab8ea29350174ec4aGuennadi Liakhovetski 15002a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); 15012a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik if (!xlate) { 15027dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_warn(icd->parent, "Format %x not found\n", pixfmt); 150325c4d74ea6f07f2aaa3df537619680ba967043f5Guennadi Liakhovetski return -EINVAL; 15042a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik } 150525c4d74ea6f07f2aaa3df537619680ba967043f5Guennadi Liakhovetski 150692a8337b380f0978ac81f096d6324d3ad689f83eRobert Jarzmik /* 15074a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho * Limit to pxa hardware capabilities. YUV422P planar format requires 15084a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho * images size to be a multiple of 16 bytes. If not, zeros will be 15094a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho * inserted between Y and U planes, and U and V planes, which violates 15104a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho * the YUV422P standard. 151192a8337b380f0978ac81f096d6324d3ad689f83eRobert Jarzmik */ 15124a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho v4l_bound_align_image(&pix->width, 48, 2048, 1, 15134a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho &pix->height, 32, 2048, 0, 15146a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0); 151592a8337b380f0978ac81f096d6324d3ad689f83eRobert Jarzmik 1516ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski /* limit to sensor capabilities */ 1517760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.width = pix->width; 1518760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.height = pix->height; 151991401219c073a565af79223215a84250bbc8c79eGuennadi Liakhovetski /* Only progressive video supported so far */ 152091401219c073a565af79223215a84250bbc8c79eGuennadi Liakhovetski mf.field = V4L2_FIELD_NONE; 1521760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.colorspace = pix->colorspace; 1522760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.code = xlate->code; 1523bf507158eb27ea94aca300b28ecee60fdbb40007Guennadi Liakhovetski 1524760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); 1525760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski if (ret < 0) 1526760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski return ret; 152706daa1af4d207e93c9a8a3e54adef8635ba81c94Guennadi Liakhovetski 1528760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski pix->width = mf.width; 1529760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski pix->height = mf.height; 1530760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski pix->colorspace = mf.colorspace; 1531760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski 1532760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski switch (mf.field) { 1533760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski case V4L2_FIELD_ANY: 1534760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski case V4L2_FIELD_NONE: 1535760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski pix->field = V4L2_FIELD_NONE; 1536760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski break; 1537760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski default: 1538760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski /* TODO: support interlaced at least in pass-through mode */ 15397dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_err(icd->parent, "Field type %d unsupported.\n", 1540760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski mf.field); 154106daa1af4d207e93c9a8a3e54adef8635ba81c94Guennadi Liakhovetski return -EINVAL; 154206daa1af4d207e93c9a8a3e54adef8635ba81c94Guennadi Liakhovetski } 154306daa1af4d207e93c9a8a3e54adef8635ba81c94Guennadi Liakhovetski 1544bf507158eb27ea94aca300b28ecee60fdbb40007Guennadi Liakhovetski return ret; 15453bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 15463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 154757bee29d6e8cf721864fa47a18366bee5ff24f21Guennadi Liakhovetskistatic int pxa_camera_reqbufs(struct soc_camera_device *icd, 15487102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski struct v4l2_requestbuffers *p) 15493bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 15503bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski int i; 15513bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 15525d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski /* 15535d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * This is for locking debugging only. I removed spinlocks and now I 15543bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * check whether .prepare is ever called on a linked buffer, or whether 15553bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * a dma IRQ can occur for an in-work or unlinked buffer. Until now 15565d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * it hadn't triggered 15575d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski */ 15583bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski for (i = 0; i < p->count; i++) { 155957bee29d6e8cf721864fa47a18366bee5ff24f21Guennadi Liakhovetski struct pxa_buffer *buf = container_of(icd->vb_vidq.bufs[i], 15603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_buffer, vb); 15613bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski buf->inwork = 0; 15623bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski INIT_LIST_HEAD(&buf->vb.queue); 15633bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 15643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 15653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return 0; 15663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 15673bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 15687102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic unsigned int pxa_camera_poll(struct file *file, poll_table *pt) 15693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 157057bee29d6e8cf721864fa47a18366bee5ff24f21Guennadi Liakhovetski struct soc_camera_device *icd = file->private_data; 15713bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_buffer *buf; 15723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 157357bee29d6e8cf721864fa47a18366bee5ff24f21Guennadi Liakhovetski buf = list_entry(icd->vb_vidq.stream.next, struct pxa_buffer, 15743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski vb.stream); 15753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 15763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski poll_wait(file, &buf->vb.done, pt); 15773bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 15783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (buf->vb.state == VIDEOBUF_DONE || 15793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski buf->vb.state == VIDEOBUF_ERROR) 15803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return POLLIN|POLLRDNORM; 15813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 15823bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return 0; 15833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 15843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 15857102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic int pxa_camera_querycap(struct soc_camera_host *ici, 15867102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski struct v4l2_capability *cap) 15873bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 15883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski /* cap->name is set by the firendly caller:-> */ 15893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card)); 15903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; 15913bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 15923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return 0; 15933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 15943bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 15957254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetskistatic int pxa_camera_suspend(struct device *dev) 15963f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik{ 15977254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(dev); 15983f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik struct pxa_camera_dev *pcdev = ici->priv; 15993f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik int i = 0, ret = 0; 16003f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 16015ca11fa3e0025864df930d6d97470b87c35919edEric Miao pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR0); 16025ca11fa3e0025864df930d6d97470b87c35919edEric Miao pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR1); 16035ca11fa3e0025864df930d6d97470b87c35919edEric Miao pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR2); 16045ca11fa3e0025864df930d6d97470b87c35919edEric Miao pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR3); 16055ca11fa3e0025864df930d6d97470b87c35919edEric Miao pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR4); 16063f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 1607497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski if (pcdev->icd) { 16087254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->icd); 1609497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski ret = v4l2_subdev_call(sd, core, s_power, 0); 1610497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski if (ret == -ENOIOCTLCMD) 1611497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski ret = 0; 1612497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski } 16133f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 16143f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik return ret; 16153f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik} 16163f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 16177254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetskistatic int pxa_camera_resume(struct device *dev) 16183f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik{ 16197254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(dev); 16203f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik struct pxa_camera_dev *pcdev = ici->priv; 16213f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik int i = 0, ret = 0; 16223f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 162387f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; 162487f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD; 162587f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD; 16263f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 16275ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(pcdev->save_cicr[i++] & ~CICR0_ENB, pcdev->base + CICR0); 16285ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR1); 16295ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR2); 16305ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR3); 16315ca11fa3e0025864df930d6d97470b87c35919edEric Miao __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR4); 16323f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 1633497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski if (pcdev->icd) { 16347254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->icd); 1635497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski ret = v4l2_subdev_call(sd, core, s_power, 1); 1636497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski if (ret == -ENOIOCTLCMD) 1637497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski ret = 0; 1638497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski } 16393f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 16403f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik /* Restart frame capture if active buffer exists */ 1641256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik if (!ret && pcdev->active) 1642256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik pxa_camera_start_capture(pcdev); 16433f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 16443f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik return ret; 16453f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik} 16463f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik 1647b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetskistatic struct soc_camera_host_ops pxa_soc_camera_host_ops = { 1648b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski .owner = THIS_MODULE, 1649b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski .add = pxa_camera_add_device, 1650b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski .remove = pxa_camera_remove_device, 165109e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski .set_crop = pxa_camera_set_crop, 16522a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik .get_formats = pxa_camera_get_formats, 16536a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski .put_formats = pxa_camera_put_formats, 1654d8fac217c58f0101a351b9c8c80f1665bd9efef9Guennadi Liakhovetski .set_fmt = pxa_camera_set_fmt, 1655d8fac217c58f0101a351b9c8c80f1665bd9efef9Guennadi Liakhovetski .try_fmt = pxa_camera_try_fmt, 1656092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas .init_videobuf = pxa_camera_init_videobuf, 1657b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski .reqbufs = pxa_camera_reqbufs, 1658b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski .poll = pxa_camera_poll, 1659b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski .querycap = pxa_camera_querycap, 1660b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski .set_bus_param = pxa_camera_set_bus_param, 1661b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski}; 1662b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski 1663e36bc31f823d6089bedc935fea82b6d36793412aJean Delvarestatic int __devinit pxa_camera_probe(struct platform_device *pdev) 16643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 16653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct pxa_camera_dev *pcdev; 16663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct resource *res; 16673bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski void __iomem *base; 166802da465945ae0a277aadf2bf37965a9e6c28f8c3Guennadi Liakhovetski int irq; 16693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski int err = 0; 16703bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 16713bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 16723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski irq = platform_get_irq(pdev, 0); 167302da465945ae0a277aadf2bf37965a9e6c28f8c3Guennadi Liakhovetski if (!res || irq < 0) { 16743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski err = -ENODEV; 16753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto exit; 16763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 16773bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 16783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); 16793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (!pcdev) { 16807102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski dev_err(&pdev->dev, "Could not allocate pcdev\n"); 16813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski err = -ENOMEM; 16823bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto exit; 16833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 16843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 1685e0d8b13ae1e3ea747620580b6f777992148de182Russell King pcdev->clk = clk_get(&pdev->dev, NULL); 16863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (IS_ERR(pcdev->clk)) { 16873bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski err = PTR_ERR(pcdev->clk); 16883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto exit_kfree; 16893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 16903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 16913bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski pcdev->res = res; 16923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 16933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski pcdev->pdata = pdev->dev.platform_data; 16943bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski pcdev->platform_flags = pcdev->pdata->flags; 1695ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | 1696ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) { 16975d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski /* 16985d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * Platform hasn't set available data widths. This is bad. 16995d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski * Warn and use a default. 17005d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski */ 17013bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " 17023bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski "data widths, using default 10 bit\n"); 17033bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10; 17043bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 1705679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8) 1706679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski pcdev->width_flags = 1 << 7; 1707679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9) 1708679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski pcdev->width_flags |= 1 << 8; 1709679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) 1710679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski pcdev->width_flags |= 1 << 9; 1711cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski pcdev->mclk = pcdev->pdata->mclk_10khz * 10000; 1712cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski if (!pcdev->mclk) { 17133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski dev_warn(&pdev->dev, 1714cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski "mclk == 0! Please, fix your platform data. " 17153bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski "Using default 20MHz\n"); 1716cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski pcdev->mclk = 20000000; 17173bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 17183bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 171940e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev); 1720cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski 17213bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski INIT_LIST_HEAD(&pcdev->capture); 17223bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski spin_lock_init(&pcdev->lock); 17233bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 17243bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski /* 17253bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * Request the regions. 17263bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski */ 1727eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski if (!request_mem_region(res->start, resource_size(res), 17283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski PXA_CAM_DRV_NAME)) { 17293bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski err = -EBUSY; 17303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto exit_clk; 17313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 17323bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 1733eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski base = ioremap(res->start, resource_size(res)); 17343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (!base) { 17353bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski err = -ENOMEM; 17363bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto exit_release; 17373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 17383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski pcdev->irq = irq; 17393bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski pcdev->base = base; 17403bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 17413bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski /* request dma */ 1742de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, 1743de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin pxa_camera_dma_irq_y, pcdev); 1744de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin if (err < 0) { 1745eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski dev_err(&pdev->dev, "Can't request DMA for Y\n"); 17463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto exit_iounmap; 17473bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 1748de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin pcdev->dma_chans[0] = err; 1749eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); 1750a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 1751de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin err = pxa_request_dma("CI_U", DMA_PRIO_HIGH, 1752de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin pxa_camera_dma_irq_u, pcdev); 1753de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin if (err < 0) { 1754eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski dev_err(&pdev->dev, "Can't request DMA for U\n"); 1755a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport goto exit_free_dma_y; 1756a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport } 1757de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin pcdev->dma_chans[1] = err; 1758eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); 1759a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport 1760de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin err = pxa_request_dma("CI_V", DMA_PRIO_HIGH, 1761de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin pxa_camera_dma_irq_v, pcdev); 1762de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin if (err < 0) { 1763eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski dev_err(&pdev->dev, "Can't request DMA for V\n"); 1764a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport goto exit_free_dma_u; 1765a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport } 1766de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin pcdev->dma_chans[2] = err; 1767eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); 17683bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 176987f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; 177087f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD; 177187f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD; 17723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 17733bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski /* request irq */ 17743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME, 17753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski pcdev); 17763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (err) { 1777eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski dev_err(&pdev->dev, "Camera interrupt register failed \n"); 17783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto exit_free_dma; 17793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski } 17803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 1781eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; 1782eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski pcdev->soc_host.ops = &pxa_soc_camera_host_ops; 1783eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski pcdev->soc_host.priv = pcdev; 1784979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski pcdev->soc_host.v4l2_dev.dev = &pdev->dev; 1785eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski pcdev->soc_host.nr = pdev->id; 1786eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski 1787eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski err = soc_camera_host_register(&pcdev->soc_host); 17883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski if (err) 17893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski goto exit_free_irq; 17903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 17913bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return 0; 17923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 17933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_free_irq: 17943bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski free_irq(pcdev->irq, pcdev); 17953bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_free_dma: 1796a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_free_dma(pcdev->dma_chans[2]); 1797a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportexit_free_dma_u: 1798a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_free_dma(pcdev->dma_chans[1]); 1799a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportexit_free_dma_y: 1800a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_free_dma(pcdev->dma_chans[0]); 18013bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_iounmap: 18023bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski iounmap(base); 18033bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_release: 1804eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski release_mem_region(res->start, resource_size(res)); 18053bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_clk: 18063bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski clk_put(pcdev->clk); 18073bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_kfree: 18083bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski kfree(pcdev); 18093bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit: 18103bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return err; 18113bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 18123bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 18133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic int __devexit pxa_camera_remove(struct platform_device *pdev) 18143bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{ 1815eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); 1816eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski struct pxa_camera_dev *pcdev = container_of(soc_host, 1817eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski struct pxa_camera_dev, soc_host); 18183bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski struct resource *res; 18193bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 18203bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski clk_put(pcdev->clk); 18213bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 1822a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_free_dma(pcdev->dma_chans[0]); 1823a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_free_dma(pcdev->dma_chans[1]); 1824a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport pxa_free_dma(pcdev->dma_chans[2]); 18253bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski free_irq(pcdev->irq, pcdev); 18263bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 1827eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski soc_camera_host_unregister(soc_host); 18283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 18293bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski iounmap(pcdev->base); 18303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 18313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski res = pcdev->res; 1832eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski release_mem_region(res->start, resource_size(res)); 18333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 18343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski kfree(pcdev); 18353bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 18367102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski dev_info(&pdev->dev, "PXA Camera driver unloaded\n"); 18373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 18383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski return 0; 18393bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski} 18403bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 18417254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetskistatic struct dev_pm_ops pxa_camera_pm = { 18427254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski .suspend = pxa_camera_suspend, 18437254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski .resume = pxa_camera_resume, 18447254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski}; 18457254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski 18463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic struct platform_driver pxa_camera_driver = { 18473bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski .driver = { 18483bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski .name = PXA_CAM_DRV_NAME, 18497254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski .pm = &pxa_camera_pm, 18503bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski }, 18513bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski .probe = pxa_camera_probe, 1852e36bc31f823d6089bedc935fea82b6d36793412aJean Delvare .remove = __devexit_p(pxa_camera_remove), 18533bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}; 18543bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 18551d6629b1561ad34a6e6d17ece00bd65e1bab3724Axel Linmodule_platform_driver(pxa_camera_driver); 18563bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski 18573bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi LiakhovetskiMODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); 18583bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi LiakhovetskiMODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); 18593bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi LiakhovetskiMODULE_LICENSE("GPL"); 186064dc3c1a906467d90c24913b0b38dd13d9378f4fMauro Carvalho ChehabMODULE_VERSION(PXA_CAM_VERSION); 186140e2e0927003424c25807b575dd40da2b8685857Guennadi LiakhovetskiMODULE_ALIAS("platform:" PXA_CAM_DRV_NAME); 1862