summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorBryan Wu <pengw@nvidia.com>2013-02-12 10:49:23 -0800
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2014-04-04 21:59:12 +0200
commit7e3151036b5e6b44fedbda0d494ff10f08a75670 (patch)
treeab3e76173215df9f80194b4b2428288087f75e79 /drivers
parent50d2dbba6198a9e195bad36990c259cfd911d53c (diff)
media: tegra: add supporting for RAW8/RAW10 input and output
CSI host controller of Tegra can support Bayer Raw8 and Raw 10 data input, it also output data as extended 16-bit data format in memory directly. Raw data output should be handled by the second output channel. This patch add supporting for Raw data input/output and the second output channel. All were tested on Cardhu board. Change-Id: Ifd1d8c94671a1d4571dcf176774e2d3cffafc399 Signed-off-by: Bryan Wu <pengw@nvidia.com> Reviewed-on: http://git-master/r/200225 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro <mapedro@nvidia.com> Conflicts: drivers/media/video/tegra_v4l2_camera.c
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/tegra_v4l2_camera.c1557
1 files changed, 844 insertions, 713 deletions
diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c
index 054415b15c73..f2a2cb907553 100644
--- a/drivers/media/video/tegra_v4l2_camera.c
+++ b/drivers/media/video/tegra_v4l2_camera.c
@@ -29,6 +29,7 @@
#include <media/soc_mediabus.h>
#include <media/videobuf2-dma-nvmap.h>
#include <media/tegra_v4l2_camera.h>
+#include <media/videobuf2-memops.h> /* for vb2_vmarea_handler */
#include <mach/powergate.h>
@@ -47,204 +48,204 @@ MODULE_PARM_DESC(internal_sync, "enable internal vsync and hsync decoded " \
#define TEGRA_SYNCPT_VI_WAIT_TIMEOUT 25
#define TEGRA_SYNCPT_CSI_WAIT_TIMEOUT 200
-#define TEGRA_SYNCPT_RETRY_COUNT 10
+#define TEGRA_SYNCPT_RETRY_COUNT 10
-#define TEGRA_VIP_H_ACTIVE_START 0x8F //0x98
-#define TEGRA_VIP_V_ACTIVE_START 0x12 //0x10
+#define TEGRA_VIP_H_ACTIVE_START 0x8F /*0x98 */
+#define TEGRA_VIP_V_ACTIVE_START 0x12 /*0x10 */
/* SYNCPTs 12-17 are reserved for VI. */
#define TEGRA_VI_SYNCPT_VI NVSYNCPT_VI_ISP_2
#define TEGRA_VI_SYNCPT_CSI NVSYNCPT_VI_ISP_3
/* Tegra CSI-MIPI registers. */
-#define TEGRA_VI_OUT_1_INCR_SYNCPT 0x0000
-#define TEGRA_VI_OUT_1_INCR_SYNCPT_CNTRL 0x0004
-#define TEGRA_VI_OUT_1_INCR_SYNCPT_ERROR 0x0008
-#define TEGRA_VI_OUT_2_INCR_SYNCPT 0x0020
-#define TEGRA_VI_OUT_2_INCR_SYNCPT_CNTRL 0x0024
-#define TEGRA_VI_OUT_2_INCR_SYNCPT_ERROR 0x0028
-#define TEGRA_VI_MISC_INCR_SYNCPT 0x0040
-#define TEGRA_VI_MISC_INCR_SYNCPT_CNTRL 0x0044
-#define TEGRA_VI_MISC_INCR_SYNCPT_ERROR 0x0048
-#define TEGRA_VI_CONT_SYNCPT_OUT_1 0x0060
-#define TEGRA_VI_CONT_SYNCPT_OUT_2 0x0064
-#define TEGRA_VI_CONT_SYNCPT_VIP_VSYNC 0x0068
-#define TEGRA_VI_CONT_SYNCPT_VI2EPP 0x006c
-#define TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_START 0x0070
-#define TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_END 0x0074
-#define TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_START 0x0078
-#define TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_END 0x007c
-#define TEGRA_VI_CTXSW 0x0080
-#define TEGRA_VI_INTSTATUS 0x0084
-#define TEGRA_VI_VI_INPUT_CONTROL 0x0088
-#define TEGRA_VI_VI_CORE_CONTROL 0x008c
-#define TEGRA_VI_VI_FIRST_OUTPUT_CONTROL 0x0090
-#define TEGRA_VI_VI_SECOND_OUTPUT_CONTROL 0x0094
-#define TEGRA_VI_HOST_INPUT_FRAME_SIZE 0x0098
-#define TEGRA_VI_HOST_H_ACTIVE 0x009c
-#define TEGRA_VI_HOST_V_ACTIVE 0x00a0
-#define TEGRA_VI_VIP_H_ACTIVE 0x00a4
-#define TEGRA_VI_VIP_V_ACTIVE 0x00a8
-#define TEGRA_VI_VI_PEER_CONTROL 0x00ac
-#define TEGRA_VI_VI_DMA_SELECT 0x00b0
-#define TEGRA_VI_HOST_DMA_WRITE_BUFFER 0x00b4
-#define TEGRA_VI_HOST_DMA_BASE_ADDRESS 0x00b8
-#define TEGRA_VI_HOST_DMA_WRITE_BUFFER_STATUS 0x00bc
-#define TEGRA_VI_HOST_DMA_WRITE_PEND_BUFCOUNT 0x00c0
-#define TEGRA_VI_VB0_START_ADDRESS_FIRST 0x00c4
-#define TEGRA_VI_VB0_BASE_ADDRESS_FIRST 0x00c8
-#define TEGRA_VI_VB0_START_ADDRESS_U 0x00cc
-#define TEGRA_VI_VB0_BASE_ADDRESS_U 0x00d0
-#define TEGRA_VI_VB0_START_ADDRESS_V 0x00d4
-#define TEGRA_VI_VB0_BASE_ADDRESS_V 0x00d8
-#define TEGRA_VI_VB_SCRATCH_ADDRESS_UV 0x00dc
-#define TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE 0x00e0
-#define TEGRA_VI_VB0_COUNT_FIRST 0x00e4
-#define TEGRA_VI_VB0_SIZE_FIRST 0x00e8
-#define TEGRA_VI_VB0_BUFFER_STRIDE_FIRST 0x00ec
-#define TEGRA_VI_VB0_START_ADDRESS_SECOND 0x00f0
-#define TEGRA_VI_VB0_BASE_ADDRESS_SECOND 0x00f4
-#define TEGRA_VI_SECOND_OUTPUT_FRAME_SIZE 0x00f8
-#define TEGRA_VI_VB0_COUNT_SECOND 0x00fc
-#define TEGRA_VI_VB0_SIZE_SECOND 0x0100
-#define TEGRA_VI_VB0_BUFFER_STRIDE_SECOND 0x0104
-#define TEGRA_VI_H_LPF_CONTROL 0x0108
-#define TEGRA_VI_H_DOWNSCALE_CONTROL 0x010c
-#define TEGRA_VI_V_DOWNSCALE_CONTROL 0x0110
-#define TEGRA_VI_CSC_Y 0x0114
-#define TEGRA_VI_CSC_UV_R 0x0118
-#define TEGRA_VI_CSC_UV_G 0x011c
-#define TEGRA_VI_CSC_UV_B 0x0120
-#define TEGRA_VI_CSC_ALPHA 0x0124
-#define TEGRA_VI_HOST_VSYNC 0x0128
-#define TEGRA_VI_COMMAND 0x012c
-#define TEGRA_VI_HOST_FIFO_STATUS 0x0130
-#define TEGRA_VI_INTERRUPT_MASK 0x0134
-#define TEGRA_VI_INTERRUPT_TYPE_SELECT 0x0138
-#define TEGRA_VI_INTERRUPT_POLARITY_SELECT 0x013c
-#define TEGRA_VI_INTERRUPT_STATUS 0x0140
-#define TEGRA_VI_VIP_INPUT_STATUS 0x0144
-#define TEGRA_VI_VIDEO_BUFFER_STATUS 0x0148
-#define TEGRA_VI_SYNC_OUTPUT 0x014c
-#define TEGRA_VI_VVS_OUTPUT_DELAY 0x0150
-#define TEGRA_VI_PWM_CONTROL 0x0154
-#define TEGRA_VI_PWM_SELECT_PULSE_A 0x0158
-#define TEGRA_VI_PWM_SELECT_PULSE_B 0x015c
-#define TEGRA_VI_PWM_SELECT_PULSE_C 0x0160
-#define TEGRA_VI_PWM_SELECT_PULSE_D 0x0164
-#define TEGRA_VI_VI_DATA_INPUT_CONTROL 0x0168
-#define TEGRA_VI_PIN_INPUT_ENABLE 0x016c
-#define TEGRA_VI_PIN_OUTPUT_ENABLE 0x0170
-#define TEGRA_VI_PIN_INVERSION 0x0174
-#define TEGRA_VI_PIN_INPUT_DATA 0x0178
-#define TEGRA_VI_PIN_OUTPUT_DATA 0x017c
-#define TEGRA_VI_PIN_OUTPUT_SELECT 0x0180
-#define TEGRA_VI_RAISE_VIP_BUFFER_FIRST_OUTPUT 0x0184
-#define TEGRA_VI_RAISE_VIP_FRAME_FIRST_OUTPUT 0x0188
-#define TEGRA_VI_RAISE_VIP_BUFFER_SECOND_OUTPUT 0x018c
-#define TEGRA_VI_RAISE_VIP_FRAME_SECOND_OUTPUT 0x0190
-#define TEGRA_VI_RAISE_HOST_FIRST_OUTPUT 0x0194
-#define TEGRA_VI_RAISE_HOST_SECOND_OUTPUT 0x0198
-#define TEGRA_VI_RAISE_EPP 0x019c
-#define TEGRA_VI_CAMERA_CONTROL 0x01a0
-#define TEGRA_VI_VI_ENABLE 0x01a4
-#define TEGRA_VI_VI_ENABLE_2 0x01a8
-#define TEGRA_VI_VI_RAISE 0x01ac
-#define TEGRA_VI_Y_FIFO_WRITE 0x01b0
-#define TEGRA_VI_U_FIFO_WRITE 0x01b4
-#define TEGRA_VI_V_FIFO_WRITE 0x01b8
-#define TEGRA_VI_VI_MCCIF_FIFOCTRL 0x01bc
-#define TEGRA_VI_TIMEOUT_WCOAL_VI 0x01c0
-#define TEGRA_VI_MCCIF_VIRUV_HP 0x01c4
-#define TEGRA_VI_MCCIF_VIWSB_HP 0x01c8
-#define TEGRA_VI_MCCIF_VIWU_HP 0x01cc
-#define TEGRA_VI_MCCIF_VIWV_HP 0x01d0
-#define TEGRA_VI_MCCIF_VIWY_HP 0x01d4
-#define TEGRA_VI_CSI_PPA_RAISE_FRAME_START 0x01d8
-#define TEGRA_VI_CSI_PPA_RAISE_FRAME_END 0x01dc
-#define TEGRA_VI_CSI_PPB_RAISE_FRAME_START 0x01e0
-#define TEGRA_VI_CSI_PBB_RAISE_FRAME_END 0x01e4
-#define TEGRA_VI_CSI_PPA_H_ACTIVE 0x01e8
-#define TEGRA_VI_CSI_PPA_V_ACTIVE 0x01ec
-#define TEGRA_VI_CSI_PPB_H_ACTIVE 0x01f0
-#define TEGRA_VI_CSI_PPB_V_ACTIVE 0x01f4
-#define TEGRA_VI_ISP_H_ACTIVE 0x01f8
-#define TEGRA_VI_ISP_V_ACTIVE 0x01fc
-#define TEGRA_VI_STREAM_1_RESOURCE_DEFINE 0x0200
-#define TEGRA_VI_STREAM_2_RESOURCE_DEFINE 0x0204
-#define TEGRA_VI_RAISE_STREAM_1_DONE 0x0208
-#define TEGRA_VI_RAISE_STREAM_2_DONE 0x020c
-#define TEGRA_VI_TS_MODE 0x0210
-#define TEGRA_VI_TS_CONTROL 0x0214
-#define TEGRA_VI_TS_PACKET_COUNT 0x0218
-#define TEGRA_VI_TS_ERROR_COUNT 0x021c
-#define TEGRA_VI_TS_CPU_FLOW_CTL 0x0220
-#define TEGRA_VI_VB0_CHROMA_BUFFER_STRIDE_FIRST 0x0224
-#define TEGRA_VI_VB0_CHROMA_LINE_STRIDE_FIRST 0x0228
-#define TEGRA_VI_EPP_LINES_PER_BUFFER 0x022c
-#define TEGRA_VI_BUFFER_RELEASE_OUTPUT1 0x0230
-#define TEGRA_VI_BUFFER_RELEASE_OUTPUT2 0x0234
-#define TEGRA_VI_DEBUG_FLOW_CONTROL_COUNTER_OUTPUT1 0x0238
-#define TEGRA_VI_DEBUG_FLOW_CONTROL_COUNTER_OUTPUT2 0x023c
-#define TEGRA_VI_TERMINATE_BW_FIRST 0x0240
-#define TEGRA_VI_TERMINATE_BW_SECOND 0x0244
-#define TEGRA_VI_VB0_FIRST_BUFFER_ADDR_MODE 0x0248
-#define TEGRA_VI_VB0_SECOND_BUFFER_ADDR_MODE 0x024c
-#define TEGRA_VI_RESERVE_0 0x0250
-#define TEGRA_VI_RESERVE_1 0x0254
-#define TEGRA_VI_RESERVE_2 0x0258
-#define TEGRA_VI_RESERVE_3 0x025c
-#define TEGRA_VI_RESERVE_4 0x0260
-#define TEGRA_VI_MCCIF_VIRUV_HYST 0x0264
-#define TEGRA_VI_MCCIF_VIWSB_HYST 0x0268
-#define TEGRA_VI_MCCIF_VIWU_HYST 0x026c
-#define TEGRA_VI_MCCIF_VIWV_HYST 0x0270
-#define TEGRA_VI_MCCIF_VIWY_HYST 0x0274
-
-#define TEGRA_CSI_VI_INPUT_STREAM_CONTROL 0x0800
-#define TEGRA_CSI_HOST_INPUT_STREAM_CONTROL 0x0808
-#define TEGRA_CSI_INPUT_STREAM_A_CONTROL 0x0810
-#define TEGRA_CSI_PIXEL_STREAM_A_CONTROL0 0x0818
-#define TEGRA_CSI_PIXEL_STREAM_A_CONTROL1 0x081c
-#define TEGRA_CSI_PIXEL_STREAM_A_WORD_COUNT 0x0820
-#define TEGRA_CSI_PIXEL_STREAM_A_GAP 0x0824
-#define TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND 0x0828
-#define TEGRA_CSI_INPUT_STREAM_B_CONTROL 0x083c
-#define TEGRA_CSI_PIXEL_STREAM_B_CONTROL0 0x0844
-#define TEGRA_CSI_PIXEL_STREAM_B_CONTROL1 0x0848
-#define TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT 0x084c
-#define TEGRA_CSI_PIXEL_STREAM_B_GAP 0x0850
-#define TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND 0x0854
-#define TEGRA_CSI_PHY_CIL_COMMAND 0x0868
-#define TEGRA_CSI_PHY_CILA_CONTROL0 0x086c
-#define TEGRA_CSI_PHY_CILB_CONTROL0 0x0870
-#define TEGRA_CSI_CSI_PIXEL_PARSER_STATUS 0x0878
-#define TEGRA_CSI_CSI_CIL_STATUS 0x087c
-#define TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK 0x0880
-#define TEGRA_CSI_CSI_CIL_INTERRUPT_MASK 0x0884
-#define TEGRA_CSI_CSI_READONLY_STATUS 0x0888
-#define TEGRA_CSI_ESCAPE_MODE_COMMAND 0x088c
-#define TEGRA_CSI_ESCAPE_MODE_DATA 0x0890
-#define TEGRA_CSI_CILA_PAD_CONFIG0 0x0894
-#define TEGRA_CSI_CILA_PAD_CONFIG1 0x0898
-#define TEGRA_CSI_CILB_PAD_CONFIG0 0x089c
-#define TEGRA_CSI_CILB_PAD_CONFIG1 0x08a0
-#define TEGRA_CSI_CIL_PAD_CONFIG 0x08a4
-#define TEGRA_CSI_CILA_MIPI_CAL_CONFIG 0x08a8
-#define TEGRA_CSI_CILB_MIPI_CAL_CONFIG 0x08ac
-#define TEGRA_CSI_CIL_MIPI_CAL_STATUS 0x08b0
-#define TEGRA_CSI_CLKEN_OVERRIDE 0x08b4
-#define TEGRA_CSI_DEBUG_CONTROL 0x08b8
-#define TEGRA_CSI_DEBUG_COUNTER_0 0x08bc
-#define TEGRA_CSI_DEBUG_COUNTER_1 0x08c0
-#define TEGRA_CSI_DEBUG_COUNTER_2 0x08c4
-#define TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME 0x08c8
-#define TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME 0x08cc
-#define TEGRA_CSI_DSI_MIPI_CAL_CONFIG 0x08d0
+#define TEGRA_VI_OUT_1_INCR_SYNCPT 0x0000
+#define TEGRA_VI_OUT_1_INCR_SYNCPT_CNTRL 0x0004
+#define TEGRA_VI_OUT_1_INCR_SYNCPT_ERROR 0x0008
+#define TEGRA_VI_OUT_2_INCR_SYNCPT 0x0020
+#define TEGRA_VI_OUT_2_INCR_SYNCPT_CNTRL 0x0024
+#define TEGRA_VI_OUT_2_INCR_SYNCPT_ERROR 0x0028
+#define TEGRA_VI_MISC_INCR_SYNCPT 0x0040
+#define TEGRA_VI_MISC_INCR_SYNCPT_CNTRL 0x0044
+#define TEGRA_VI_MISC_INCR_SYNCPT_ERROR 0x0048
+#define TEGRA_VI_CONT_SYNCPT_OUT_1 0x0060
+#define TEGRA_VI_CONT_SYNCPT_OUT_2 0x0064
+#define TEGRA_VI_CONT_SYNCPT_VIP_VSYNC 0x0068
+#define TEGRA_VI_CONT_SYNCPT_VI2EPP 0x006c
+#define TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_START 0x0070
+#define TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_END 0x0074
+#define TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_START 0x0078
+#define TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_END 0x007c
+#define TEGRA_VI_CTXSW 0x0080
+#define TEGRA_VI_INTSTATUS 0x0084
+#define TEGRA_VI_VI_INPUT_CONTROL 0x0088
+#define TEGRA_VI_VI_CORE_CONTROL 0x008c
+#define TEGRA_VI_VI_FIRST_OUTPUT_CONTROL 0x0090
+#define TEGRA_VI_VI_SECOND_OUTPUT_CONTROL 0x0094
+#define TEGRA_VI_HOST_INPUT_FRAME_SIZE 0x0098
+#define TEGRA_VI_HOST_H_ACTIVE 0x009c
+#define TEGRA_VI_HOST_V_ACTIVE 0x00a0
+#define TEGRA_VI_VIP_H_ACTIVE 0x00a4
+#define TEGRA_VI_VIP_V_ACTIVE 0x00a8
+#define TEGRA_VI_VI_PEER_CONTROL 0x00ac
+#define TEGRA_VI_VI_DMA_SELECT 0x00b0
+#define TEGRA_VI_HOST_DMA_WRITE_BUFFER 0x00b4
+#define TEGRA_VI_HOST_DMA_BASE_ADDRESS 0x00b8
+#define TEGRA_VI_HOST_DMA_WRITE_BUFFER_STATUS 0x00bc
+#define TEGRA_VI_HOST_DMA_WRITE_PEND_BUFCOUNT 0x00c0
+#define TEGRA_VI_VB0_START_ADDRESS_FIRST 0x00c4
+#define TEGRA_VI_VB0_BASE_ADDRESS_FIRST 0x00c8
+#define TEGRA_VI_VB0_START_ADDRESS_U 0x00cc
+#define TEGRA_VI_VB0_BASE_ADDRESS_U 0x00d0
+#define TEGRA_VI_VB0_START_ADDRESS_V 0x00d4
+#define TEGRA_VI_VB0_BASE_ADDRESS_V 0x00d8
+#define TEGRA_VI_VB_SCRATCH_ADDRESS_UV 0x00dc
+#define TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE 0x00e0
+#define TEGRA_VI_VB0_COUNT_FIRST 0x00e4
+#define TEGRA_VI_VB0_SIZE_FIRST 0x00e8
+#define TEGRA_VI_VB0_BUFFER_STRIDE_FIRST 0x00ec
+#define TEGRA_VI_VB0_START_ADDRESS_SECOND 0x00f0
+#define TEGRA_VI_VB0_BASE_ADDRESS_SECOND 0x00f4
+#define TEGRA_VI_SECOND_OUTPUT_FRAME_SIZE 0x00f8
+#define TEGRA_VI_VB0_COUNT_SECOND 0x00fc
+#define TEGRA_VI_VB0_SIZE_SECOND 0x0100
+#define TEGRA_VI_VB0_BUFFER_STRIDE_SECOND 0x0104
+#define TEGRA_VI_H_LPF_CONTROL 0x0108
+#define TEGRA_VI_H_DOWNSCALE_CONTROL 0x010c
+#define TEGRA_VI_V_DOWNSCALE_CONTROL 0x0110
+#define TEGRA_VI_CSC_Y 0x0114
+#define TEGRA_VI_CSC_UV_R 0x0118
+#define TEGRA_VI_CSC_UV_G 0x011c
+#define TEGRA_VI_CSC_UV_B 0x0120
+#define TEGRA_VI_CSC_ALPHA 0x0124
+#define TEGRA_VI_HOST_VSYNC 0x0128
+#define TEGRA_VI_COMMAND 0x012c
+#define TEGRA_VI_HOST_FIFO_STATUS 0x0130
+#define TEGRA_VI_INTERRUPT_MASK 0x0134
+#define TEGRA_VI_INTERRUPT_TYPE_SELECT 0x0138
+#define TEGRA_VI_INTERRUPT_POLARITY_SELECT 0x013c
+#define TEGRA_VI_INTERRUPT_STATUS 0x0140
+#define TEGRA_VI_VIP_INPUT_STATUS 0x0144
+#define TEGRA_VI_VIDEO_BUFFER_STATUS 0x0148
+#define TEGRA_VI_SYNC_OUTPUT 0x014c
+#define TEGRA_VI_VVS_OUTPUT_DELAY 0x0150
+#define TEGRA_VI_PWM_CONTROL 0x0154
+#define TEGRA_VI_PWM_SELECT_PULSE_A 0x0158
+#define TEGRA_VI_PWM_SELECT_PULSE_B 0x015c
+#define TEGRA_VI_PWM_SELECT_PULSE_C 0x0160
+#define TEGRA_VI_PWM_SELECT_PULSE_D 0x0164
+#define TEGRA_VI_VI_DATA_INPUT_CONTROL 0x0168
+#define TEGRA_VI_PIN_INPUT_ENABLE 0x016c
+#define TEGRA_VI_PIN_OUTPUT_ENABLE 0x0170
+#define TEGRA_VI_PIN_INVERSION 0x0174
+#define TEGRA_VI_PIN_INPUT_DATA 0x0178
+#define TEGRA_VI_PIN_OUTPUT_DATA 0x017c
+#define TEGRA_VI_PIN_OUTPUT_SELECT 0x0180
+#define TEGRA_VI_RAISE_VIP_BUFFER_FIRST_OUTPUT 0x0184
+#define TEGRA_VI_RAISE_VIP_FRAME_FIRST_OUTPUT 0x0188
+#define TEGRA_VI_RAISE_VIP_BUFFER_SECOND_OUTPUT 0x018c
+#define TEGRA_VI_RAISE_VIP_FRAME_SECOND_OUTPUT 0x0190
+#define TEGRA_VI_RAISE_HOST_FIRST_OUTPUT 0x0194
+#define TEGRA_VI_RAISE_HOST_SECOND_OUTPUT 0x0198
+#define TEGRA_VI_RAISE_EPP 0x019c
+#define TEGRA_VI_CAMERA_CONTROL 0x01a0
+#define TEGRA_VI_VI_ENABLE 0x01a4
+#define TEGRA_VI_VI_ENABLE_2 0x01a8
+#define TEGRA_VI_VI_RAISE 0x01ac
+#define TEGRA_VI_Y_FIFO_WRITE 0x01b0
+#define TEGRA_VI_U_FIFO_WRITE 0x01b4
+#define TEGRA_VI_V_FIFO_WRITE 0x01b8
+#define TEGRA_VI_VI_MCCIF_FIFOCTRL 0x01bc
+#define TEGRA_VI_TIMEOUT_WCOAL_VI 0x01c0
+#define TEGRA_VI_MCCIF_VIRUV_HP 0x01c4
+#define TEGRA_VI_MCCIF_VIWSB_HP 0x01c8
+#define TEGRA_VI_MCCIF_VIWU_HP 0x01cc
+#define TEGRA_VI_MCCIF_VIWV_HP 0x01d0
+#define TEGRA_VI_MCCIF_VIWY_HP 0x01d4
+#define TEGRA_VI_CSI_PPA_RAISE_FRAME_START 0x01d8
+#define TEGRA_VI_CSI_PPA_RAISE_FRAME_END 0x01dc
+#define TEGRA_VI_CSI_PPB_RAISE_FRAME_START 0x01e0
+#define TEGRA_VI_CSI_PBB_RAISE_FRAME_END 0x01e4
+#define TEGRA_VI_CSI_PPA_H_ACTIVE 0x01e8
+#define TEGRA_VI_CSI_PPA_V_ACTIVE 0x01ec
+#define TEGRA_VI_CSI_PPB_H_ACTIVE 0x01f0
+#define TEGRA_VI_CSI_PPB_V_ACTIVE 0x01f4
+#define TEGRA_VI_ISP_H_ACTIVE 0x01f8
+#define TEGRA_VI_ISP_V_ACTIVE 0x01fc
+#define TEGRA_VI_STREAM_1_RESOURCE_DEFINE 0x0200
+#define TEGRA_VI_STREAM_2_RESOURCE_DEFINE 0x0204
+#define TEGRA_VI_RAISE_STREAM_1_DONE 0x0208
+#define TEGRA_VI_RAISE_STREAM_2_DONE 0x020c
+#define TEGRA_VI_TS_MODE 0x0210
+#define TEGRA_VI_TS_CONTROL 0x0214
+#define TEGRA_VI_TS_PACKET_COUNT 0x0218
+#define TEGRA_VI_TS_ERROR_COUNT 0x021c
+#define TEGRA_VI_TS_CPU_FLOW_CTL 0x0220
+#define TEGRA_VI_VB0_CHROMA_BUFFER_STRIDE_FIRST 0x0224
+#define TEGRA_VI_VB0_CHROMA_LINE_STRIDE_FIRST 0x0228
+#define TEGRA_VI_EPP_LINES_PER_BUFFER 0x022c
+#define TEGRA_VI_BUFFER_RELEASE_OUTPUT1 0x0230
+#define TEGRA_VI_BUFFER_RELEASE_OUTPUT2 0x0234
+#define TEGRA_VI_DEBUG_FLOW_CONTROL_COUNTER_OUTPUT1 0x0238
+#define TEGRA_VI_DEBUG_FLOW_CONTROL_COUNTER_OUTPUT2 0x023c
+#define TEGRA_VI_TERMINATE_BW_FIRST 0x0240
+#define TEGRA_VI_TERMINATE_BW_SECOND 0x0244
+#define TEGRA_VI_VB0_FIRST_BUFFER_ADDR_MODE 0x0248
+#define TEGRA_VI_VB0_SECOND_BUFFER_ADDR_MODE 0x024c
+#define TEGRA_VI_RESERVE_0 0x0250
+#define TEGRA_VI_RESERVE_1 0x0254
+#define TEGRA_VI_RESERVE_2 0x0258
+#define TEGRA_VI_RESERVE_3 0x025c
+#define TEGRA_VI_RESERVE_4 0x0260
+#define TEGRA_VI_MCCIF_VIRUV_HYST 0x0264
+#define TEGRA_VI_MCCIF_VIWSB_HYST 0x0268
+#define TEGRA_VI_MCCIF_VIWU_HYST 0x026c
+#define TEGRA_VI_MCCIF_VIWV_HYST 0x0270
+#define TEGRA_VI_MCCIF_VIWY_HYST 0x0274
+
+#define TEGRA_CSI_VI_INPUT_STREAM_CONTROL 0x0800
+#define TEGRA_CSI_HOST_INPUT_STREAM_CONTROL 0x0808
+#define TEGRA_CSI_INPUT_STREAM_A_CONTROL 0x0810
+#define TEGRA_CSI_PIXEL_STREAM_A_CONTROL0 0x0818
+#define TEGRA_CSI_PIXEL_STREAM_A_CONTROL1 0x081c
+#define TEGRA_CSI_PIXEL_STREAM_A_WORD_COUNT 0x0820
+#define TEGRA_CSI_PIXEL_STREAM_A_GAP 0x0824
+#define TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND 0x0828
+#define TEGRA_CSI_INPUT_STREAM_B_CONTROL 0x083c
+#define TEGRA_CSI_PIXEL_STREAM_B_CONTROL0 0x0844
+#define TEGRA_CSI_PIXEL_STREAM_B_CONTROL1 0x0848
+#define TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT 0x084c
+#define TEGRA_CSI_PIXEL_STREAM_B_GAP 0x0850
+#define TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND 0x0854
+#define TEGRA_CSI_PHY_CIL_COMMAND 0x0868
+#define TEGRA_CSI_PHY_CILA_CONTROL0 0x086c
+#define TEGRA_CSI_PHY_CILB_CONTROL0 0x0870
+#define TEGRA_CSI_CSI_PIXEL_PARSER_STATUS 0x0878
+#define TEGRA_CSI_CSI_CIL_STATUS 0x087c
+#define TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK 0x0880
+#define TEGRA_CSI_CSI_CIL_INTERRUPT_MASK 0x0884
+#define TEGRA_CSI_CSI_READONLY_STATUS 0x0888
+#define TEGRA_CSI_ESCAPE_MODE_COMMAND 0x088c
+#define TEGRA_CSI_ESCAPE_MODE_DATA 0x0890
+#define TEGRA_CSI_CILA_PAD_CONFIG0 0x0894
+#define TEGRA_CSI_CILA_PAD_CONFIG1 0x0898
+#define TEGRA_CSI_CILB_PAD_CONFIG0 0x089c
+#define TEGRA_CSI_CILB_PAD_CONFIG1 0x08a0
+#define TEGRA_CSI_CIL_PAD_CONFIG 0x08a4
+#define TEGRA_CSI_CILA_MIPI_CAL_CONFIG 0x08a8
+#define TEGRA_CSI_CILB_MIPI_CAL_CONFIG 0x08ac
+#define TEGRA_CSI_CIL_MIPI_CAL_STATUS 0x08b0
+#define TEGRA_CSI_CLKEN_OVERRIDE 0x08b4
+#define TEGRA_CSI_DEBUG_CONTROL 0x08b8
+#define TEGRA_CSI_DEBUG_COUNTER_0 0x08bc
+#define TEGRA_CSI_DEBUG_COUNTER_1 0x08c0
+#define TEGRA_CSI_DEBUG_COUNTER_2 0x08c4
+#define TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME 0x08c8
+#define TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME 0x08cc
+#define TEGRA_CSI_DSI_MIPI_CAL_CONFIG 0x08d0
#define IS_INTERLACED ((pcdev->field == V4L2_FIELD_INTERLACED)\
- || (pcdev->field == V4L2_FIELD_INTERLACED_BT)\
- || (pcdev->field == V4L2_FIELD_INTERLACED_TB))
+ || (pcdev->field == V4L2_FIELD_INTERLACED_BT)\
+ || (pcdev->field == V4L2_FIELD_INTERLACED_TB))
#define TC_VI_REG_RD(DEV, REG) readl(DEV->vi_base + REG)
#define TC_VI_REG_WT(DEV, REG, VAL) writel(VAL, DEV->vi_base + REG)
@@ -263,107 +264,165 @@ MODULE_PARM_DESC(internal_sync, "enable internal vsync and hsync decoded " \
/* buffer for one video frame */
struct tegra_buffer {
- struct vb2_buffer vb; /* v4l buffer must be first */
- struct list_head queue;
+ struct vb2_buffer vb; /* v4l buffer must be first */
+ struct list_head queue;
/*
* Various buffer addresses shadowed so we don't have to recalculate
* per frame. These are calculated during videobuf_prepare.
*/
- dma_addr_t buffer_addr;
- dma_addr_t buffer_addr_u;
- dma_addr_t buffer_addr_v;
- dma_addr_t start_addr;
- dma_addr_t start_addr_u;
- dma_addr_t start_addr_v;
- void* virtual_addr;
-
- dma_addr_t internal_phys_addr;
- void* internal_virtual_addr;
+ dma_addr_t buffer_addr;
+ dma_addr_t buffer_addr_u;
+ dma_addr_t buffer_addr_v;
+ dma_addr_t start_addr;
+ dma_addr_t start_addr_u;
+ dma_addr_t start_addr_v;
+ void *virtual_addr;
+
+ dma_addr_t internal_phys_addr;
+ void *internal_virtual_addr;
};
struct tegra_camera_dev {
- struct soc_camera_host ici;
- struct soc_camera_device *icd;
- struct nvhost_device *ndev;
+ struct soc_camera_host ici;
+ struct soc_camera_device *icd;
+ struct nvhost_device *ndev;
struct tegra_camera_platform_data *pdata;
- struct clk *clk_vi;
- struct clk *clk_vi_sensor;
- struct clk *clk_csi;
- struct clk *clk_isp;
- struct clk *clk_csus;
+ struct clk *clk_vi;
+ struct clk *clk_vi_sensor;
+ struct clk *clk_csi;
+ struct clk *clk_isp;
+ struct clk *clk_csus;
- void __iomem *vi_base;
- spinlock_t videobuf_queue_lock;
- struct list_head capture;
- struct vb2_buffer *active;
- struct vb2_alloc_ctx *alloc_ctx;
- enum v4l2_field field;
- int sequence;
+ void __iomem *vi_base;
+ spinlock_t videobuf_queue_lock;
+ struct list_head capture;
+ struct vb2_buffer *active;
+ struct vb2_alloc_ctx *alloc_ctx;
+ enum v4l2_field field;
+ int sequence;
- struct work_struct work;
- struct mutex work_mutex;
+ struct work_struct work;
+ struct mutex work_mutex;
- u32 syncpt_vi;
- u32 syncpt_csi;
+ u32 syncpt_vi;
+ u32 syncpt_csi;
/* private buffer for non-interlaced frame */
struct vb2_dc_buf *internal_vbuf;
/* Debug */
int num_frames;
+
+ int output_channel;
};
static const struct soc_mbus_pixelfmt tegra_camera_formats[] = {
{
- .fourcc = V4L2_PIX_FMT_UYVY,
- .name = "YUV422 (UYVY) packed",
- .bits_per_sample = 16,
- .packing = SOC_MBUS_PACKING_NONE,
- .order = SOC_MBUS_ORDER_LE,
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .name = "YUV422 (UYVY) packed",
+ .bits_per_sample = 16,
+ .packing = SOC_MBUS_PACKING_NONE,
+ .order = SOC_MBUS_ORDER_LE,
},
{
- .fourcc = V4L2_PIX_FMT_VYUY,
- .name = "YUV422 (VYUY) packed",
- .bits_per_sample = 16,
- .packing = SOC_MBUS_PACKING_NONE,
- .order = SOC_MBUS_ORDER_LE,
+ .fourcc = V4L2_PIX_FMT_VYUY,
+ .name = "YUV422 (VYUY) packed",
+ .bits_per_sample = 16,
+ .packing = SOC_MBUS_PACKING_NONE,
+ .order = SOC_MBUS_ORDER_LE,
},
{
- .fourcc = V4L2_PIX_FMT_YUYV,
- .name = "YUV422 (YUYV) packed",
- .bits_per_sample = 16,
- .packing = SOC_MBUS_PACKING_NONE,
- .order = SOC_MBUS_ORDER_LE,
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .name = "YUV422 (YUYV) packed",
+ .bits_per_sample = 16,
+ .packing = SOC_MBUS_PACKING_NONE,
+ .order = SOC_MBUS_ORDER_LE,
},
{
- .fourcc = V4L2_PIX_FMT_YVYU,
- .name = "YUV422 (YVYU) packed",
- .bits_per_sample = 16,
- .packing = SOC_MBUS_PACKING_NONE,
- .order = SOC_MBUS_ORDER_LE,
+ .fourcc = V4L2_PIX_FMT_YVYU,
+ .name = "YUV422 (YVYU) packed",
+ .bits_per_sample = 16,
+ .packing = SOC_MBUS_PACKING_NONE,
+ .order = SOC_MBUS_ORDER_LE,
},
{
- .fourcc = V4L2_PIX_FMT_YUV420,
- .name = "YUV420 (YU12) planar",
- .bits_per_sample = 12,
- .packing = SOC_MBUS_PACKING_NONE,
- .order = SOC_MBUS_ORDER_LE,
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .name = "YUV420 (YU12) planar",
+ .bits_per_sample = 12,
+ .packing = SOC_MBUS_PACKING_NONE,
+ .order = SOC_MBUS_ORDER_LE,
},
{
- .fourcc = V4L2_PIX_FMT_YVU420,
- .name = "YVU420 (YV12) planar",
- .bits_per_sample = 12,
- .packing = SOC_MBUS_PACKING_NONE,
- .order = SOC_MBUS_ORDER_LE,
+ .fourcc = V4L2_PIX_FMT_YVU420,
+ .name = "YVU420 (YV12) planar",
+ .bits_per_sample = 12,
+ .packing = SOC_MBUS_PACKING_NONE,
+ .order = SOC_MBUS_ORDER_LE,
},
+
+ /* For RAW8 and RAW10 output, we always output 16-bit (2 bytes). */
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG8,
+ .name = "Bayer 8 GRGR.. BGBG..",
+ .bits_per_sample = 16,
+ .packing = SOC_MBUS_PACKING_EXTEND16,
+ .order = SOC_MBUS_ORDER_LE,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG10,
+ .name = "Bayer 10 GRGR.. BGBG..",
+ .bits_per_sample = 16,
+ .packing = SOC_MBUS_PACKING_EXTEND16,
+ .order = SOC_MBUS_ORDER_LE,
+ },
+
};
+/* interlace related stuff */
struct thread_args {
struct tegra_camera_dev *pcdev;
struct tegra_buffer *tb;
};
+void interlace_and_copy(void *dst, void *src, int width, int height)
+{
+ int l;
+
+ for (l = 0; l <= (height - 1); l++) {
+ if (l < (height / 2))
+ memcpy(dst + (width * (2 * l)), (void *) ((unsigned int)(src) + (width * l)), width);
+ else
+ memcpy(dst + (width * (2 * (l - (height / 2)) + 1)), (void *) ((unsigned int)(src) + (width * l)), width);
+ }
+}
+
+int make_interlaced(void *arg)
+{
+ struct thread_args *ta = arg;
+ struct soc_camera_device *icd = ta->pcdev->icd;
+ void *src = ta->tb->internal_virtual_addr;
+ void *dst = ta->tb->virtual_addr;
+ int bytes_per_line;
+
+ if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_YUV420 || icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_YVU420) {
+ interlace_and_copy(dst, src, icd->user_width, icd->user_height); /* Y */
+ interlace_and_copy(dst + (icd->user_width * icd->user_height),
+ src + (icd->user_width * icd->user_height),
+ icd->user_width,
+ icd->user_height / 4); /* U */
+ interlace_and_copy(dst + (icd->user_width * icd->user_height) + (icd->user_width * icd->user_height) / 4,
+ src + (icd->user_width * icd->user_height) + (icd->user_width * icd->user_height) / 4,
+ icd->user_width,
+ icd->user_height / 4); /* V */
+ } else {
+ bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt);
+ interlace_and_copy(dst, src, bytes_per_line, icd->user_height); /* Y, U, V */
+ }
+ do_exit(0);
+}
+/*/ */
+
static struct tegra_buffer *to_tegra_vb(struct vb2_buffer *vb)
{
return container_of(vb, struct tegra_buffer, vb);
@@ -373,45 +432,24 @@ static void tegra_camera_save_syncpts(struct tegra_camera_dev *pcdev)
{
pcdev->syncpt_csi =
nvhost_syncpt_read_ext(pcdev->ndev,
- TEGRA_VI_SYNCPT_CSI);
+ TEGRA_VI_SYNCPT_CSI);
pcdev->syncpt_vi =
nvhost_syncpt_read_ext(pcdev->ndev,
- TEGRA_VI_SYNCPT_VI);
+ TEGRA_VI_SYNCPT_VI);
}
static void tegra_camera_incr_syncpts(struct tegra_camera_dev *pcdev)
{
nvhost_syncpt_cpu_incr_ext(pcdev->ndev,
- TEGRA_VI_SYNCPT_CSI);
+ TEGRA_VI_SYNCPT_CSI);
nvhost_syncpt_cpu_incr_ext(pcdev->ndev,
- TEGRA_VI_SYNCPT_VI);
+ TEGRA_VI_SYNCPT_VI);
}
-static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev,
- int input_format,
- int yuv_input_format)
+static void tegra_camera_capture_clean(struct tegra_camera_dev *pcdev)
{
- struct soc_camera_device *icd = pcdev->icd;
- int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
- icd->current_fmt->host_fmt);
-
- TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x02000000);
-
- TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL,
- (yuv_input_format << 8) |
- (input_format << 2));
-
- TC_VI_REG_WT(pcdev, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000004);
- TC_VI_REG_WT(pcdev, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000004);
-
- /* CSI-A H_ACTIVE and V_ACTIVE */
- TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_H_ACTIVE,
- (icd->user_width << 16));
- TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_V_ACTIVE,
- (icd->user_height << 16));
-
/* CSI A */
TC_VI_REG_WT(pcdev, TEGRA_CSI_VI_INPUT_STREAM_CONTROL, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_CSI_HOST_INPUT_STREAM_CONTROL, 0x00000000);
@@ -421,51 +459,124 @@ static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev,
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_WORD_COUNT, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_GAP, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_B_CONTROL, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL1, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_GAP, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0x00000000);
+
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILA_CONTROL0, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILB_CONTROL0, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_CIL_STATUS, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_CIL_INTERRUPT_MASK, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_READONLY_STATUS, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_ESCAPE_MODE_COMMAND, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_ESCAPE_MODE_DATA, 0x0);
+
TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_PAD_CONFIG0, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_PAD_CONFIG1, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG0, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG1, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_CSI_CIL_PAD_CONFIG, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_MIPI_CAL_CONFIG, 0x00000000);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_CSI_CIL_MIPI_CAL_STATUS, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_CSI_CLKEN_OVERRIDE, 0x00000000);
- /* pad1s enabled, virtual channel ID 00 */
- TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_CONTROL0,
- (0x1 << 16) | /* Output 1 pixel per clock */
- (0x1e << 8) | /* If hdr shows wrong fmt, use YUV422 */
- (0x1 << 7) | /* Check header CRC */
- (0x1 << 6) | /* Use word count field in the header */
- (0x1 << 5) | /* Look at data identifier byte in hdr */
- (0x1 << 4)); /* Expect packet header */
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_CONTROL, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_COUNTER_0, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_COUNTER_1, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_COUNTER_2, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME, 0x0);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME, 0x0);
+}
+
+static u32 tegra_camera_header_for_wrong_fmt(struct tegra_camera_dev *pcdev)
+{
+ struct soc_camera_device *icd = pcdev->icd;
+ const struct soc_camera_format_xlate *current_fmt = icd->current_fmt;
+ enum v4l2_mbus_pixelcode input_code = current_fmt->code;
+ u32 hdr;
+
+ switch (input_code) {
+ case V4L2_MBUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
+ hdr = 30;
+ break;
+ case V4L2_MBUS_FMT_SGRBG8_1X8:
+ hdr = 42;
+ break;
+ case V4L2_MBUS_FMT_SGRBG10_1X10:
+ hdr = 43;
+ break;
+ default:
+ BUG_ON(1);
+ }
+
+ return hdr;
+}
+
+static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev,
+ u32 input_control)
+{
+ struct soc_camera_device *icd = pcdev->icd;
+ int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+ icd->current_fmt->host_fmt);
+ u32 hdr = tegra_camera_header_for_wrong_fmt(pcdev);
+
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x02000000);
+
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL, input_control);
+
+ TC_VI_REG_WT(pcdev, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000004);
+ TC_VI_REG_WT(pcdev, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000004);
+
+ /* CSI-A H_ACTIVE and V_ACTIVE */
+ TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_H_ACTIVE,
+ (icd->user_width << 16));
+ TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_V_ACTIVE,
+ (icd->user_height << 16));
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_CONTROL1,
- 0x1); /* Frame # for top field detect for interlaced */
+ 0x1); /* Frame # for top field detect for interlaced */
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_WORD_COUNT,
- bytes_per_line);
+ bytes_per_line);
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_GAP, 0x00140000);
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME,
- (icd->user_height << 16) |
- (0x100 << 4) | /* Wait 0x100 vi clks for timeout */
- 0x1); /* Enable line timeout */
+ (icd->user_height << 16) |
+ (0x100 << 4) | /* Wait 0x100 vi clks for timeout */
+ 0x1); /* Enable line timeout */
+
+ /* pad 0s enabled, virtual channel ID 00 */
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_CONTROL0,
+ (0x1 << 16) | /* Output 1 pixel per clock */
+ (hdr << 8) | /* If hdr shows wrong fmt, use right value */
+ (0x1 << 7) | /* Check header CRC */
+ (0x1 << 6) | /* Use word count field in the header */
+ (0x1 << 5) | /* Look at data identifier byte in hdr */
+ (0x1 << 4)); /* Expect packet header */
TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_A_CONTROL,
- (0x3f << 16) | /* Skip packet threshold */
- (pcdev->pdata->lanes - 1));
+ (0x3f << 16) | /* Skip packet threshold */
+ (pcdev->pdata->lanes - 1));
/* Use 0x00000022 for continuous clock mode. */
TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILA_CONTROL0,
- (pcdev->pdata->continuous_clk << 5) |
- 0x5); /* Clock settle time */
+ (pcdev->pdata->continuous_clk << 5) |
+ 0x5); /* Clock settle time */
TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_END,
- (0x1 << 8) | /* Enable continuous syncpt */
- TEGRA_VI_SYNCPT_CSI);
-
- TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_OUT_1,
- (0x1 << 8) | /* Enable continuous syncpt */
- TEGRA_VI_SYNCPT_VI);
+ (0x1 << 8) | /* Enable continuous syncpt */
+ TEGRA_VI_SYNCPT_CSI);
TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00020001);
@@ -473,83 +584,60 @@ static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev,
}
static void tegra_camera_capture_setup_csi_b(struct tegra_camera_dev *pcdev,
- int input_format,
- int yuv_input_format)
+ u32 input_control)
{
struct soc_camera_device *icd = pcdev->icd;
int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
- icd->current_fmt->host_fmt);
+ icd->current_fmt->host_fmt);
+ u32 hdr = tegra_camera_header_for_wrong_fmt(pcdev);
TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x04000000);
- TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL,
- (yuv_input_format << 8) |
- (input_format << 2));
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL, input_control);
TC_VI_REG_WT(pcdev, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000008);
TC_VI_REG_WT(pcdev, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000008);
/* CSI-B H_ACTIVE and V_ACTIVE */
TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPB_H_ACTIVE,
- (icd->user_width << 16));
+ (icd->user_width << 16));
TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPB_V_ACTIVE,
- (icd->user_height << 16));
-
- /* CSI B */
- TC_VI_REG_WT(pcdev, TEGRA_CSI_VI_INPUT_STREAM_CONTROL, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_HOST_INPUT_STREAM_CONTROL, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_B_CONTROL, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL1, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_GAP, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0x00000000);
-
- TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG0, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG1, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_CIL_PAD_CONFIG, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_CIL_MIPI_CAL_STATUS, 0x00000000);
- TC_VI_REG_WT(pcdev, TEGRA_CSI_CLKEN_OVERRIDE, 0x00000000);
+ (icd->user_height << 16));
- /* pad1s enabled, virtual channel ID 00 */
+ /* pad 0s enabled, virtual channel ID 00 */
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0,
- (0x1 << 16) | /* Output 1 pixel per clock */
- (0x1e << 8) | /* If hdr shows wrong fmt, use YUV422 */
- (0x1 << 7) | /* Check header CRC */
- (0x1 << 6) | /* Use word count field in the header */
- (0x1 << 5) | /* Look at data identifier byte in hdr */
- (0x1 << 4) | /* Expect packet header */
- 0x1); /* Set PPB stream source to CSI B */
+ (0x1 << 16) | /* Output 1 pixel per clock */
+ (hdr << 8) | /* If hdr shows wrong fmt, use right value */
+ (0x1 << 7) | /* Check header CRC */
+ (0x1 << 6) | /* Use word count field in the header */
+ (0x1 << 5) | /* Look at data identifier byte in hdr */
+ (0x1 << 4) | /* Expect packet header */
+ 0x1); /* Set PPB stream source to CSI B */
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL1,
- 0x1); /* Frame # for top field detect for interlaced */
+ 0x1); /* Frame # for top field detect for interlaced */
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT,
- bytes_per_line);
+ bytes_per_line);
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_GAP, 0x00140000);
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME,
- (icd->user_height << 16) |
- (0x100 << 4) | /* Wait 0x100 vi clks for timeout */
- 0x1); /* Enable line timeout */
+ (icd->user_height << 16) |
+ (0x100 << 4) | /* Wait 0x100 vi clks for timeout */
+ 0x1); /* Enable line timeout */
TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_B_CONTROL,
- (0x3f << 16) | /* Skip packet threshold */
- (pcdev->pdata->lanes - 1));
+ (0x3f << 16) | /* Skip packet threshold */
+ (pcdev->pdata->lanes - 1));
/* Use 0x00000022 for continuous clock mode. */
TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILB_CONTROL0,
- (pcdev->pdata->continuous_clk << 5) |
- 0x5); /* Clock settle time */
+ (pcdev->pdata->continuous_clk << 5) |
+ 0x5); /* Clock settle time */
TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_END,
- (0x1 << 8) | /* Enable continuous syncpt */
- TEGRA_VI_SYNCPT_CSI);
-
- TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_OUT_1,
- (0x1 << 8) | /* Enable continuous syncpt */
- TEGRA_VI_SYNCPT_VI);
+ (0x1 << 8) | /* Enable continuous syncpt */
+ TEGRA_VI_SYNCPT_CSI);
TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00010002);
@@ -557,8 +645,7 @@ static void tegra_camera_capture_setup_csi_b(struct tegra_camera_dev *pcdev,
}
static void tegra_camera_capture_setup_vip(struct tegra_camera_dev *pcdev,
- int input_format,
- int yuv_input_format)
+ u32 input_control)
{
struct soc_camera_device *icd = pcdev->icd;
@@ -566,117 +653,206 @@ static void tegra_camera_capture_setup_vip(struct tegra_camera_dev *pcdev,
TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL,
-// (1 << 27) | /* field detect */
- (0 << 28) | /* 1 == top field is even field, 00 == odd */
- ((internal_sync == 1) << 25) | /* 1 == hsync/vsync decoded
- internally from data
- (BT.656) */
- (yuv_input_format << 8) |
- (1 << 1) | /* VIP_INPUT_ENABLE */
- (input_format << 2));
+ /* (1 << 27) | field detect */
+ (0 << 28) | /* 1 == top field is even field, 00 == odd */
+ ((internal_sync == 1) << 25) | /* 1 == hsync/vsync decoded
+ internally from data
+ (BT.656) */
+ /* (yuv_input_format << 8) | */
+ (1 << 1) | /* VIP_INPUT_ENABLE */
+ input_control);
TC_VI_REG_WT(pcdev, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000000);
/* VIP H_ACTIVE and V_ACTIVE */
TC_VI_REG_WT(pcdev, TEGRA_VI_VIP_H_ACTIVE,
- (icd->user_width << 16) |
- (TEGRA_VIP_H_ACTIVE_START - ((internal_sync == 1)?1:0)));
+ (icd->user_width << 16) |
+ (TEGRA_VIP_H_ACTIVE_START - ((internal_sync == 1) ? 1 : 0)));
TC_VI_REG_WT(pcdev, TEGRA_VI_VIP_V_ACTIVE,
- ( ( IS_INTERLACED ? (icd->user_height/2) : (icd->user_height) ) << 16) |
- TEGRA_VIP_V_ACTIVE_START);
+ ((IS_INTERLACED ? (icd->user_height / 2) : (icd->user_height)) << 16) |
+ TEGRA_VIP_V_ACTIVE_START);
/*
* For VIP, D9..D2 is mapped to the video decoder's P7..P0.
* Disable/mask out the other Dn wires.
*/
- TC_VI_REG_WT(pcdev, TEGRA_VI_PIN_INPUT_ENABLE, 0x000003fc | 0x6000); // D2..D9 + VSYNC + HSYNC
+ TC_VI_REG_WT(pcdev, TEGRA_VI_PIN_INPUT_ENABLE, 0x000003fc | 0x6000); /* D2..D9 + VSYNC + HSYNC */
TC_VI_REG_WT(pcdev, TEGRA_VI_VI_DATA_INPUT_CONTROL, 0x000003fc);
TC_VI_REG_WT(pcdev, TEGRA_VI_PIN_INVERSION, 0x00000000);
TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_OUT_1,
- (0x1 << 8) | /* Enable continuous syncpt */
- TEGRA_VI_SYNCPT_VI);
+ (0x1 << 8) | /* Enable continuous syncpt */
+ TEGRA_VI_SYNCPT_VI);
-// TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL, 0x00000004);
+ /* TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL, 0x00000004); */
}
struct vb2_dc_buf {
- struct vb2_dc_conf *conf;
- void *vaddr;
- dma_addr_t paddr;
- unsigned long size;
- struct vm_area_struct *vma;
- atomic_t refcount;
- //struct vb2_vmarea_handler handler;
-
- struct nvmap_handle_ref *nvmap_ref;
+ struct vb2_dc_conf *conf;
+ void *vaddr;
+ dma_addr_t paddr;
+ unsigned long size;
+ struct vm_area_struct *vma;
+ atomic_t refcount;
+ struct vb2_vmarea_handler handler;
+
+ struct nvmap_handle_ref *nvmap_ref;
};
-static void tegra_camera_capture_setup(struct tegra_camera_dev *pcdev)
+static void tegra_camera_capture_output_channel_setup(
+ struct tegra_camera_dev *pcdev)
{
struct soc_camera_device *icd = pcdev->icd;
+ int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+ icd->current_fmt->host_fmt);
const struct soc_camera_format_xlate *current_fmt = icd->current_fmt;
- enum v4l2_mbus_pixelcode input_code = current_fmt->code;
u32 output_fourcc = current_fmt->host_fmt->fourcc;
- int yuv_input_format = 0x0;
- int input_format = 0x0; /* Default to YUV422 */
- int yuv_output_format = 0x0;
- int output_format = 0x3; /* Default to YUV422 */
+ u32 output_format, output_control;
int port = pcdev->pdata->port;
- int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
- icd->current_fmt->host_fmt);
- int frame_count = 1;
-
- // prepare internal_vbuf in case of later interlacing
- if(IS_INTERLACED)
- {
- if(output_fourcc == V4L2_PIX_FMT_YUV420 || output_fourcc == V4L2_PIX_FMT_YVU420)
- pcdev->internal_vbuf = vb2_dma_nvmap_memops.alloc(pcdev->alloc_ctx, ((icd->user_height * icd->user_width) + (icd->user_height * icd->user_width)/2 ));
- else
- pcdev->internal_vbuf = vb2_dma_nvmap_memops.alloc(pcdev->alloc_ctx, (icd->user_height * bytes_per_line));
- }
-
- switch (input_code) {
- case V4L2_MBUS_FMT_UYVY8_2X8:
- yuv_input_format = 0x2;
- break;
- case V4L2_MBUS_FMT_VYUY8_2X8:
- yuv_input_format = 0x3;
- break;
- case V4L2_MBUS_FMT_YUYV8_2X8:
- yuv_input_format = 0x0;
- break;
- case V4L2_MBUS_FMT_YVYU8_2X8:
- yuv_input_format = 0x1;
- break;
- default:
- BUG_ON(1);
- }
+ int frame_count;
switch (output_fourcc) {
case V4L2_PIX_FMT_UYVY:
- yuv_output_format = 0x0;
+ output_format = 0x3; /* Default to YUV422 */
break;
case V4L2_PIX_FMT_VYUY:
- yuv_output_format = 0x1;
+ output_format = (0x1 << 17) | 0x3;
break;
case V4L2_PIX_FMT_YUYV:
- yuv_output_format = 0x2;
+ output_format = (0x2 << 17) | 0x3;
break;
case V4L2_PIX_FMT_YVYU:
- yuv_output_format = 0x3;
+ output_format = (0x3 << 17) | 0x3;
break;
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
output_format = 0x6; /* YUV420 planar */
break;
+ case V4L2_PIX_FMT_SBGGR8:
+ case V4L2_PIX_FMT_SBGGR10:
+ /* Use second output channel for RAW8/RAW10 */
+ pcdev->output_channel = 1;
+
+ if (port == TEGRA_CAMERA_PORT_CSI_A)
+ output_format = 0x7;
+ else if (port == TEGRA_CAMERA_PORT_CSI_B)
+ output_format = 0x8;
+ else
+ output_format = 0x9;
+ break;
default:
BUG_ON(1);
}
+ /* prepare internal_vbuf in case of later interlacing */
+ if (IS_INTERLACED) {
+ if (output_fourcc == V4L2_PIX_FMT_YUV420 || output_fourcc == V4L2_PIX_FMT_YVU420)
+ pcdev->internal_vbuf = vb2_dma_nvmap_memops.alloc(pcdev->alloc_ctx, ((icd->user_height * icd->user_width) + (icd->user_height * icd->user_width) / 2));
+ else
+ pcdev->internal_vbuf = vb2_dma_nvmap_memops.alloc(pcdev->alloc_ctx, (icd->user_height * bytes_per_line));
+ }
+
+ output_control = (pcdev->pdata->flip_v ? (0x1 << 20) : 0) |
+ (pcdev->pdata->flip_h ? (0x1 << 19) : 0) |
+ output_format;
+
+ /* if the video is interlaced, then take two frames */
+ frame_count = IS_INTERLACED ? 2 : 1;
+
+ if (pcdev->output_channel == 0) {
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL,
+ output_control);
+
+ /*
+ * Set up frame size. Bits 31:16 are the number of lines, and
+ * bits 15:0 are the number of pixels per line.
+ */
+ TC_VI_REG_WT(pcdev, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE,
+ ((icd->user_height / frame_count) << 16) | icd->user_width);
+
+ /* First output memory enabled */
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE, 0x00000000);
+
+ /* Set the number of frames in the buffer. */
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_COUNT_FIRST, frame_count);
+
+ /* Set up buffer frame size. */
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_SIZE_FIRST,
+ ((icd->user_height / frame_count) << 16) | icd->user_width);
+
+ if (output_fourcc == V4L2_PIX_FMT_YUV420 || output_fourcc == V4L2_PIX_FMT_YVU420) {
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST,
+ ((icd->user_height / frame_count) * icd->user_width) | (2 << 30));
+ } else {
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST,
+ ((icd->user_height / frame_count) * bytes_per_line) | (2 << 30));
+ }
+
+ TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_OUT_1,
+ (0x1 << 8) | /* Enable continuous syncpt */
+ TEGRA_VI_SYNCPT_VI);
+
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE, 0x00000000);
+
+ } else if (pcdev->output_channel == 1) {
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_SECOND_OUTPUT_CONTROL,
+ output_control);
+
+ TC_VI_REG_WT(pcdev, TEGRA_VI_SECOND_OUTPUT_FRAME_SIZE,
+ (icd->user_height << 16) | icd->user_width);
+
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE_2, 0x00000000);
+
+ /* Set the number of frames in the buffer. */
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_COUNT_SECOND, 0x00000001);
+
+ /* Set up buffer frame size. */
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_SIZE_SECOND,
+ (icd->user_height << 16) | icd->user_width);
+
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BUFFER_STRIDE_SECOND,
+ (icd->user_height * bytes_per_line));
+
+ TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_OUT_2,
+ (0x1 << 8) | /* Enable continuous syncpt */
+ TEGRA_VI_SYNCPT_VI);
+
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE_2, 0x00000000);
+ }
+}
+
+static void tegra_camera_capture_setup(struct tegra_camera_dev *pcdev)
+{
+ struct soc_camera_device *icd = pcdev->icd;
+ const struct soc_camera_format_xlate *current_fmt = icd->current_fmt;
+ enum v4l2_mbus_pixelcode input_code = current_fmt->code;
+ u32 input_control = 0x0;
+ int port = pcdev->pdata->port;
+
BUG_ON(!tegra_camera_port_is_valid(port));
+ switch (input_code) {
+ case V4L2_MBUS_FMT_UYVY8_2X8:
+ input_control |= 0x2 << 8;
+ break;
+ case V4L2_MBUS_FMT_VYUY8_2X8:
+ input_control |= 0x3 << 8;
+ break;
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ input_control |= 0x0;
+ break;
+ case V4L2_MBUS_FMT_YVYU8_2X8:
+ input_control |= 0x1 << 8;
+ break;
+ case V4L2_MBUS_FMT_SGRBG8_1X8:
+ case V4L2_MBUS_FMT_SGRBG10_1X10:
+ input_control |= 0x2 << 2; /* Input Format = Bayer */
+ break;
+ default:
+ BUG_ON(1);
+ }
+
/*
* Set up low pass filter. Use 0x240 for chromaticity and 0x240
* for luminance, which is the default and means not to touch
@@ -687,144 +863,91 @@ static void tegra_camera_capture_setup(struct tegra_camera_dev *pcdev)
/* Set up raise-on-edge, so we get an interrupt on end of frame. */
TC_VI_REG_WT(pcdev, TEGRA_VI_VI_RAISE, 0x00000001);
+ /* Cleanup registers */
+ tegra_camera_capture_clean(pcdev);
+
+ /* Setup registers for CSI-A, CSI-B and VIP inputs */
if (port == TEGRA_CAMERA_PORT_CSI_A)
- tegra_camera_capture_setup_csi_a(pcdev, input_format,
- yuv_input_format);
+ tegra_camera_capture_setup_csi_a(pcdev, input_control);
else if (port == TEGRA_CAMERA_PORT_CSI_B)
- tegra_camera_capture_setup_csi_b(pcdev, input_format,
- yuv_input_format);
+ tegra_camera_capture_setup_csi_b(pcdev, input_control);
else
- tegra_camera_capture_setup_vip(pcdev, input_format,
- yuv_input_format);
-
- TC_VI_REG_WT(pcdev, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL,
- (pcdev->pdata->flip_v ? (0x1 << 20) : 0) |
- (pcdev->pdata->flip_h ? (0x1 << 19) : 0) |
- (yuv_output_format << 17) |
- output_format);
-
- // if the video is interlaced, then take two frames
- frame_count = IS_INTERLACED ? 2 : 1;
-
- /*
- * Set up frame size. Bits 31:16 are the number of lines, and
- * bits 15:0 are the number of pixels per line.
- */
- TC_VI_REG_WT(pcdev, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE,
- ((icd->user_height/frame_count) << 16) | icd->user_width);
-
- /* Set the number of frames in the buffer. */
- TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_COUNT_FIRST, frame_count);
-
- /* Set up buffer frame size. */
- TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_SIZE_FIRST,
- ((icd->user_height/frame_count) << 16) | icd->user_width);
- if(output_fourcc == V4L2_PIX_FMT_YUV420 || output_fourcc == V4L2_PIX_FMT_YVU420) {
- TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST,
- ((icd->user_height/frame_count) * icd->user_width) | (2<<30));
- }
- else {
- TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST,
- ((icd->user_height/frame_count) * bytes_per_line) | (2<<30));
- }
-
- /* First output memory enabled */
- TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE, 0x00000000);
-}
-
-void interlace_and_copy(void* dst, void* src, int width, int height)
-{
- int l;
-
- for(l = 0; l <= (height-1); l++)
- {
- if(l < (height/2))
- memcpy(dst + (width * (2 * l)), (void*) ((unsigned int)(src) + (width * l)), width);
- else
- memcpy(dst + (width * (2 * (l-(height/2)) + 1) ), (void*) ((unsigned int)(src) + (width * l)), width);
- }
-}
-
-int make_interlaced(void* arg)
-{
- struct thread_args *ta = arg;
- struct soc_camera_device *icd = ta->pcdev->icd;
- void *src = ta->tb->internal_virtual_addr;
- void *dst = ta->tb->virtual_addr;
- int bytes_per_line;
-
- if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_YUV420 || icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_YVU420 )
- {
- interlace_and_copy(dst, src, icd->user_width, icd->user_height); // Y
- interlace_and_copy(dst + (icd->user_width * icd->user_height),
- src + (icd->user_width * icd->user_height),
- icd->user_width,
- icd->user_height/4); // U
- interlace_and_copy(dst + (icd->user_width * icd->user_height) + (icd->user_width * icd->user_height)/4,
- src + (icd->user_width * icd->user_height) + (icd->user_width * icd->user_height)/4,
- icd->user_width,
- icd->user_height/4); // V
- }
- else
- {
- bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt);
- interlace_and_copy(dst, src, bytes_per_line, icd->user_height); // Y, U, V
- }
- do_exit(0);
+ tegra_camera_capture_setup_vip(pcdev, input_control);
+ tegra_camera_capture_output_channel_setup(pcdev);
}
-static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev,
- struct tegra_buffer *buf)
+static void tegra_camera_capture_buffer_setup(struct tegra_camera_dev *pcdev,
+ struct tegra_buffer *buf)
{
struct soc_camera_device *icd = pcdev->icd;
- int port = pcdev->pdata->port;
- int err;
- struct task_struct *interlace_task;
- struct thread_args ta;
switch (icd->current_fmt->host_fmt->fourcc) {
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_U,
- buf->buffer_addr_u);
+ buf->buffer_addr_u);
TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_U,
- buf->start_addr_u);
+ buf->start_addr_u);
TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_V,
- buf->buffer_addr_v);
+ buf->buffer_addr_v);
TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_V,
- buf->start_addr_v);
+ buf->start_addr_v);
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_VYUY:
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
- TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_FIRST,
- buf->buffer_addr);
- TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_FIRST,
- buf->start_addr);
-
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SGRBG10:
+ /* output 1 */
+ if (!pcdev->output_channel) {
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_FIRST,
+ buf->buffer_addr);
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_FIRST,
+ buf->start_addr);
+ /* output 2 */
+ } else if (pcdev->output_channel == 1) {
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_SECOND,
+ buf->buffer_addr);
+ TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_SECOND,
+ buf->start_addr);
+ }
break;
default:
BUG_ON(1);
}
+}
+
+static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev,
+ struct tegra_buffer *buf)
+{
+ int port = pcdev->pdata->port;
+ int err;
+
+ struct task_struct *interlace_task;
+ struct thread_args ta;
BUG_ON(!tegra_camera_port_is_valid(port));
+ pcdev->syncpt_csi++;
+ pcdev->syncpt_vi++;
+
+ tegra_camera_capture_buffer_setup(pcdev, buf);
+
if (port == TEGRA_CAMERA_PORT_CSI_A)
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
- 0x0000f005);
+ 0x0000f005);
else if (port == TEGRA_CAMERA_PORT_CSI_B)
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
- 0x0000f005);
+ 0x0000f005);
else
TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL,
- 0x00000005); // start & stop
+ 0x00000005); /* start & stop */
- // start the interlacing task now
- if(IS_INTERLACED)
- {
+ /* start the interlacing task now */
+ if (IS_INTERLACED) {
ta.tb = buf;
ta.pcdev = pcdev;
interlace_task = kthread_run(make_interlaced, &ta, "interlacing thread");
@@ -839,34 +962,34 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev,
if (tegra_camera_port_is_csi(port))
err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev,
- TEGRA_VI_SYNCPT_CSI,
- pcdev->syncpt_csi,
- TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
- NULL);
+ TEGRA_VI_SYNCPT_CSI,
+ pcdev->syncpt_csi,
+ TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
+ NULL);
else
err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev,
- TEGRA_VI_SYNCPT_VI,
- pcdev->syncpt_vi,
- TEGRA_SYNCPT_VI_WAIT_TIMEOUT,
- NULL);
+ TEGRA_VI_SYNCPT_VI,
+ pcdev->syncpt_vi,
+ TEGRA_SYNCPT_VI_WAIT_TIMEOUT,
+ NULL);
- if (IS_INTERLACED) {
+ if (IS_INTERLACED) {
- TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL,
- 0x00000005); // start & stop
+ TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL,
+ 0x00000005); /* start & stop */
- pcdev->syncpt_vi++;
- pcdev->syncpt_csi++;
+ pcdev->syncpt_vi++;
+ pcdev->syncpt_csi++;
- err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev,
- TEGRA_VI_SYNCPT_VI,
- pcdev->syncpt_vi,
- TEGRA_SYNCPT_VI_WAIT_TIMEOUT,
- NULL);
- }
+ err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev,
+ TEGRA_VI_SYNCPT_VI,
+ pcdev->syncpt_vi,
+ TEGRA_SYNCPT_VI_WAIT_TIMEOUT,
+ NULL);
+ }
- if (!err)
- return 0;
+ if (!err)
+ return 0;
if (tegra_camera_port_is_csi(port)) {
u32 ppstatus;
@@ -875,33 +998,33 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev,
dev_err(&pcdev->ndev->dev, "Timeout on CSI syncpt\n");
dev_err(&pcdev->ndev->dev, "buffer_addr = 0x%08x\n",
- buf->buffer_addr);
+ buf->buffer_addr);
ppstatus = TC_VI_REG_RD(pcdev,
- TEGRA_CSI_CSI_PIXEL_PARSER_STATUS);
+ TEGRA_CSI_CSI_PIXEL_PARSER_STATUS);
cilstatus = TC_VI_REG_RD(pcdev,
- TEGRA_CSI_CSI_CIL_STATUS);
+ TEGRA_CSI_CSI_CIL_STATUS);
rostatus = TC_VI_REG_RD(pcdev,
- TEGRA_CSI_CSI_READONLY_STATUS);
+ TEGRA_CSI_CSI_READONLY_STATUS);
dev_err(&pcdev->ndev->dev,
- "PPSTATUS = 0x%08x, "
- "CILSTATUS = 0x%08x, "
- "ROSTATUS = 0x%08x\n",
- ppstatus, cilstatus, rostatus);
+ "PPSTATUS = 0x%08x, "
+ "CILSTATUS = 0x%08x, "
+ "ROSTATUS = 0x%08x\n",
+ ppstatus, cilstatus, rostatus);
} else {
u32 vip_input_status;
dev_err(&pcdev->ndev->dev, "Timeout on VI syncpt\n");
dev_err(&pcdev->ndev->dev, "buffer_addr = 0x%08x\n",
- buf->buffer_addr);
+ buf->buffer_addr);
vip_input_status = TC_VI_REG_RD(pcdev,
- TEGRA_VI_VIP_INPUT_STATUS);
+ TEGRA_VI_VIP_INPUT_STATUS);
dev_err(&pcdev->ndev->dev,
- "VIP_INPUT_STATUS = 0x%08x\n",
- vip_input_status);
+ "VIP_INPUT_STATUS = 0x%08x\n",
+ vip_input_status);
}
return err;
}
@@ -915,20 +1038,20 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev)
if (port == TEGRA_CAMERA_PORT_CSI_A)
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
- 0x0000f002);
+ 0x0000f002);
else if (port == TEGRA_CAMERA_PORT_CSI_B)
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
- 0x0000f002);
-// else
-// TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL,
-// 0x00000005);
+ 0x0000f002);
+ /* else */
+ /* TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL, */
+ /* 0x00000005); */
if (tegra_camera_port_is_csi(port))
err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev,
- TEGRA_VI_SYNCPT_VI,
- pcdev->syncpt_vi,
- TEGRA_SYNCPT_VI_WAIT_TIMEOUT,
- NULL);
+ TEGRA_VI_SYNCPT_VI,
+ pcdev->syncpt_vi,
+ TEGRA_SYNCPT_VI_WAIT_TIMEOUT,
+ NULL);
else
err = 0;
@@ -938,18 +1061,23 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev)
u32 cilstatus;
dev_err(&pcdev->ndev->dev, "Timeout on VI syncpt\n");
- buffer_addr = TC_VI_REG_RD(pcdev,
- TEGRA_VI_VB0_BASE_ADDRESS_FIRST);
+
+ if (!pcdev->output_channel)
+ buffer_addr = TC_VI_REG_RD(pcdev,
+ TEGRA_VI_VB0_BASE_ADDRESS_FIRST);
+ else
+ buffer_addr = TC_VI_REG_RD(pcdev,
+ TEGRA_VI_VB0_BASE_ADDRESS_SECOND);
dev_err(&pcdev->ndev->dev, "buffer_addr = 0x%08x\n",
- buffer_addr);
+ buffer_addr);
ppstatus = TC_VI_REG_RD(pcdev,
- TEGRA_CSI_CSI_PIXEL_PARSER_STATUS);
+ TEGRA_CSI_CSI_PIXEL_PARSER_STATUS);
cilstatus = TC_VI_REG_RD(pcdev,
- TEGRA_CSI_CSI_CIL_STATUS);
+ TEGRA_CSI_CSI_CIL_STATUS);
dev_err(&pcdev->ndev->dev,
- "PPSTATUS = 0x%08x, CILSTATUS = 0x%08x\n",
- ppstatus, cilstatus);
+ "PPSTATUS = 0x%08x, CILSTATUS = 0x%08x\n",
+ ppstatus, cilstatus);
}
return err;
@@ -973,36 +1101,37 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev)
err = tegra_camera_capture_start(pcdev, buf);
if (err == 0) {
err = tegra_camera_capture_stop(pcdev);
- if (err == 0) break;
+ if (err == 0)
+ break;
}
/* Stop streaming. */
if (port == TEGRA_CAMERA_PORT_CSI_A) {
TC_VI_REG_WT(pcdev,
- TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
- 0x0000f002);
+ TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
+ 0x0000f002);
/* Clear status registers. */
TC_VI_REG_WT(pcdev,
- TEGRA_CSI_CSI_PIXEL_PARSER_STATUS,
- 0xffffffff);
+ TEGRA_CSI_CSI_PIXEL_PARSER_STATUS,
+ 0xffffffff);
TC_VI_REG_WT(pcdev,
- TEGRA_CSI_CSI_CIL_STATUS,
- 0xffffffff);
+ TEGRA_CSI_CSI_CIL_STATUS,
+ 0xffffffff);
} else if (port == TEGRA_CAMERA_PORT_CSI_B) {
TC_VI_REG_WT(pcdev,
- TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
- 0x0000f002);
+ TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
+ 0x0000f002);
/* Clear status registers. */
TC_VI_REG_WT(pcdev,
- TEGRA_CSI_CSI_PIXEL_PARSER_STATUS,
- 0xffffffff);
+ TEGRA_CSI_CSI_PIXEL_PARSER_STATUS,
+ 0xffffffff);
TC_VI_REG_WT(pcdev,
- TEGRA_CSI_CSI_CIL_STATUS,
- 0xffffffff);
+ TEGRA_CSI_CSI_CIL_STATUS,
+ 0xffffffff);
} else {
TC_VI_REG_WT(pcdev,
- TEGRA_VI_CAMERA_CONTROL,
- 0x00000005);
+ TEGRA_VI_CAMERA_CONTROL,
+ 0x00000005);
}
tegra_camera_incr_syncpts(pcdev);
@@ -1021,7 +1150,7 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev)
if (!list_empty(&pcdev->capture))
pcdev->active = &list_entry(pcdev->capture.next,
- struct tegra_buffer, queue)->vb;
+ struct tegra_buffer, queue)->vb;
else
pcdev->active = NULL;
@@ -1029,8 +1158,8 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev)
vb->v4l2_buf.field = pcdev->field;
vb->v4l2_buf.sequence = pcdev->sequence++;
- if(IS_INTERLACED && pcdev->num_frames==0)
- // if we're dealing with interlaced frames, tell V4L to remove the frame from the queue
+ if (IS_INTERLACED && pcdev->num_frames == 0)
+ /* if we're dealing with interlaced frames, tell V4L to remove the frame from the queue */
vb2_buffer_done(vb, VB2_BUF_STATE_DEQUEUED);
else
vb2_buffer_done(vb, (err != 0) ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
@@ -1065,8 +1194,8 @@ static void tegra_camera_activate(struct tegra_camera_dev *pcdev)
nvhost_module_busy_ext(pcdev->ndev);
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- if(!tegra_powergate_is_powered(TEGRA_POWERGATE_VENC))
- tegra_unpowergate_partition(TEGRA_POWERGATE_VENC);
+ if (!tegra_powergate_is_powered(TEGRA_POWERGATE_VENC))
+ tegra_unpowergate_partition(TEGRA_POWERGATE_VENC);
#endif
/* Turn on relevant clocks. */
@@ -1111,33 +1240,33 @@ static void tegra_camera_deactivate(struct tegra_camera_dev *pcdev)
}
static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev,
- struct tegra_buffer *buf)
+ struct tegra_buffer *buf)
{
struct soc_camera_device *icd = pcdev->icd;
int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
- icd->current_fmt->host_fmt);
+ icd->current_fmt->host_fmt);
- if(IS_INTERLACED)
- {
- buf->internal_phys_addr = pcdev->internal_vbuf->paddr; // physical addr of internal buffer
- buf->internal_virtual_addr = pcdev->internal_vbuf->vaddr; // virtual address of internal buffer
- buf->buffer_addr = buf->internal_phys_addr; // internal buffer -> buffer for decoding
- buf->virtual_addr = vb2_plane_vaddr(&buf->vb, 0); // save virtual addr for later interlace handling
- }
- else
- buf->buffer_addr = vb2_dma_nvmap_plane_paddr(&buf->vb, 0); // physical addr
+ if (IS_INTERLACED) {
+ buf->internal_phys_addr = pcdev->internal_vbuf->paddr; /* physical addr of internal buffer */
+ buf->internal_virtual_addr = pcdev->internal_vbuf->vaddr; /* virtual address of internal buffer */
+ buf->buffer_addr = buf->internal_phys_addr; /* internal buffer -> buffer for decoding */
+ buf->virtual_addr = vb2_plane_vaddr(&buf->vb, 0); /* save virtual addr for later interlace handling */
+ } else
+ buf->buffer_addr = vb2_dma_nvmap_plane_paddr(&buf->vb, 0); /* physical addr */
switch (icd->current_fmt->host_fmt->fourcc) {
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_VYUY:
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SGRBG10:
buf->start_addr = buf->buffer_addr;
if (pcdev->pdata->flip_v)
buf->start_addr += bytes_per_line *
- (icd->user_height-1);
+ (icd->user_height - 1);
if (pcdev->pdata->flip_h)
buf->start_addr += bytes_per_line - 1;
@@ -1147,9 +1276,9 @@ static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev,
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
buf->buffer_addr_u = buf->buffer_addr +
- icd->user_width * icd->user_height;
+ icd->user_width * icd->user_height;
buf->buffer_addr_v = buf->buffer_addr_u +
- (icd->user_width * icd->user_height) / 4;
+ (icd->user_width * icd->user_height) / 4;
/* For YVU420, we swap the locations of the U and V planes. */
if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_YVU420) {
@@ -1164,21 +1293,21 @@ static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev,
if (pcdev->pdata->flip_v) {
buf->start_addr += icd->user_width *
- (icd->user_height - 1);
+ (icd->user_height - 1);
- buf->start_addr_u += ((icd->user_width/2) *
- ((icd->user_height/2) - 1));
+ buf->start_addr_u += ((icd->user_width / 2) *
+ ((icd->user_height / 2) - 1));
- buf->start_addr_v += ((icd->user_width/2) *
- ((icd->user_height/2) - 1));
+ buf->start_addr_v += ((icd->user_width / 2) *
+ ((icd->user_height / 2) - 1));
}
if (pcdev->pdata->flip_h) {
buf->start_addr += icd->user_width - 1;
- buf->start_addr_u += (icd->user_width/2) - 1;
+ buf->start_addr_u += (icd->user_width / 2) - 1;
- buf->start_addr_v += (icd->user_width/2) - 1;
+ buf->start_addr_v += (icd->user_width / 2) - 1;
}
break;
@@ -1192,18 +1321,18 @@ static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev,
* Videobuf operations
*/
static int tegra_camera_videobuf_setup(struct vb2_queue *vq,
- unsigned int *num_buffers,
- unsigned int *num_planes,
- unsigned long sizes[],
- void *alloc_ctxs[])
+ unsigned int *num_buffers,
+ unsigned int *num_planes,
+ unsigned long sizes[],
+ void *alloc_ctxs[])
{
struct soc_camera_device *icd = container_of(vq,
- struct soc_camera_device,
- vb2_vidq);
+ struct soc_camera_device,
+ vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct tegra_camera_dev *pcdev = ici->priv;
int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
- icd->current_fmt->host_fmt);
+ icd->current_fmt->host_fmt);
dev_dbg(icd->parent, "In tegra_camera_videobuf_setup()\n");
@@ -1220,7 +1349,7 @@ static int tegra_camera_videobuf_setup(struct vb2_queue *vq,
*num_buffers = 2;
dev_dbg(icd->parent, "num_buffers=%u, size=%lu\n",
- *num_buffers, sizes[0]);
+ *num_buffers, sizes[0]);
tegra_camera_capture_setup(pcdev);
@@ -1232,13 +1361,13 @@ static int tegra_camera_videobuf_setup(struct vb2_queue *vq,
static int tegra_camera_videobuf_prepare(struct vb2_buffer *vb)
{
struct soc_camera_device *icd = container_of(vb->vb2_queue,
- struct soc_camera_device,
- vb2_vidq);
+ struct soc_camera_device,
+ vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct tegra_camera_dev *pcdev = ici->priv;
struct tegra_buffer *buf;
int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
- icd->current_fmt->host_fmt);
+ icd->current_fmt->host_fmt);
unsigned long size;
dev_dbg(icd->parent, "In tegra_camera_videobuf_prepare()\n");
@@ -1249,7 +1378,7 @@ static int tegra_camera_videobuf_prepare(struct vb2_buffer *vb)
buf = to_tegra_vb(vb);
dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
- vb, vb2_plane_vaddr(vb, 0), vb2_plane_size(vb, 0));
+ vb, vb2_plane_vaddr(vb, 0), vb2_plane_size(vb, 0));
#ifdef PREFILL_BUFFER
/*
@@ -1266,7 +1395,7 @@ static int tegra_camera_videobuf_prepare(struct vb2_buffer *vb)
if (vb2_plane_size(vb, 0) < size) {
dev_err(icd->parent, "Buffer too small (%lu < %lu)\n",
- vb2_plane_size(vb, 0), size);
+ vb2_plane_size(vb, 0), size);
return -ENOBUFS;
}
@@ -1282,8 +1411,8 @@ static int tegra_camera_videobuf_prepare(struct vb2_buffer *vb)
static void tegra_camera_videobuf_queue(struct vb2_buffer *vb)
{
struct soc_camera_device *icd = container_of(vb->vb2_queue,
- struct soc_camera_device,
- vb2_vidq);
+ struct soc_camera_device,
+ vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct tegra_camera_dev *pcdev = ici->priv;
struct tegra_buffer *buf = to_tegra_vb(vb);
@@ -1291,7 +1420,7 @@ static void tegra_camera_videobuf_queue(struct vb2_buffer *vb)
dev_dbg(icd->parent, "In tegra_camera_videobuf_queue()\n");
dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
- vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
+ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
spin_lock_irq(&pcdev->videobuf_queue_lock);
list_add_tail(&buf->queue, &pcdev->capture);
@@ -1308,16 +1437,15 @@ static void tegra_camera_videobuf_queue(struct vb2_buffer *vb)
static void tegra_camera_videobuf_release(struct vb2_buffer *vb)
{
struct soc_camera_device *icd = container_of(vb->vb2_queue,
- struct soc_camera_device,
- vb2_vidq);
+ struct soc_camera_device,
+ vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct tegra_buffer *buf = to_tegra_vb(vb);
struct tegra_camera_dev *pcdev = ici->priv;
dev_dbg(icd->parent, "In tegra_camera_videobuf_release()\n");
- if(IS_INTERLACED && pcdev->internal_vbuf!=NULL)
- {
+ if (IS_INTERLACED && pcdev->internal_vbuf != NULL) {
vb2_dma_nvmap_memops.put(pcdev->internal_vbuf);
pcdev->internal_vbuf = NULL;
}
@@ -1354,8 +1482,8 @@ static int tegra_camera_videobuf_init(struct vb2_buffer *vb)
static int tegra_camera_stop_streaming(struct vb2_queue *q)
{
struct soc_camera_device *icd = container_of(q,
- struct soc_camera_device,
- vb2_vidq);
+ struct soc_camera_device,
+ vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct tegra_camera_dev *pcdev = ici->priv;
struct list_head *buf_head, *tmp;
@@ -1377,21 +1505,21 @@ static int tegra_camera_stop_streaming(struct vb2_queue *q)
}
static struct vb2_ops tegra_camera_videobuf_ops = {
- .queue_setup = tegra_camera_videobuf_setup,
- .buf_prepare = tegra_camera_videobuf_prepare,
- .buf_queue = tegra_camera_videobuf_queue,
- .buf_cleanup = tegra_camera_videobuf_release,
- .buf_init = tegra_camera_videobuf_init,
- .wait_prepare = soc_camera_unlock,
- .wait_finish = soc_camera_lock,
- .stop_streaming = tegra_camera_stop_streaming,
+ .queue_setup = tegra_camera_videobuf_setup,
+ .buf_prepare = tegra_camera_videobuf_prepare,
+ .buf_queue = tegra_camera_videobuf_queue,
+ .buf_cleanup = tegra_camera_videobuf_release,
+ .buf_init = tegra_camera_videobuf_init,
+ .wait_prepare = soc_camera_unlock,
+ .wait_finish = soc_camera_lock,
+ .stop_streaming = tegra_camera_stop_streaming,
};
/*
* SOC camera host operations
*/
static int tegra_camera_init_videobuf(struct vb2_queue *q,
- struct soc_camera_device *icd)
+ struct soc_camera_device *icd)
{
dev_dbg(icd->parent, "In tegra_camera_init_videobuf()\n");
@@ -1400,7 +1528,7 @@ static int tegra_camera_init_videobuf(struct vb2_queue *q,
q->drv_priv = icd;
q->ops = &tegra_camera_videobuf_ops;
q->mem_ops = &vb2_dma_nvmap_memops;
- //q->mem_ops = &am_vb2_dma_nvmap_memops;
+ /*q->mem_ops = &am_vb2_dma_nvmap_memops; */
q->buf_struct_size = sizeof(struct tegra_buffer);
dev_dbg(icd->parent, "Finished tegra_camera_init_videobuf()\n");
@@ -1433,9 +1561,10 @@ static int tegra_camera_add_device(struct soc_camera_device *icd)
pcdev->icd = icd;
pcdev->num_frames = 0;
+ pcdev->output_channel = 0;
dev_dbg(icd->parent, "TEGRA Camera host attached to camera %d\n",
- icd->devnum);
+ icd->devnum);
return 0;
}
@@ -1458,18 +1587,18 @@ static void tegra_camera_remove_device(struct soc_camera_device *icd)
dev_dbg(icd->parent, "Frames captured: %d\n", pcdev->num_frames);
dev_dbg(icd->parent, "TEGRA camera host detached from camera %d\n",
- icd->devnum);
+ icd->devnum);
}
static int tegra_camera_set_bus_param(struct soc_camera_device *icd,
- __u32 pixfmt)
+ __u32 pixfmt)
{
return 0;
}
static int tegra_camera_get_formats(struct soc_camera_device *icd,
- unsigned int idx,
- struct soc_camera_format_xlate *xlate)
+ unsigned int idx,
+ struct soc_camera_format_xlate *xlate)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent;
@@ -1495,16 +1624,18 @@ static int tegra_camera_get_formats(struct soc_camera_device *icd,
case V4L2_MBUS_FMT_VYUY8_2X8:
case V4L2_MBUS_FMT_YUYV8_2X8:
case V4L2_MBUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_SGRBG8_1X8:
+ case V4L2_MBUS_FMT_SGRBG10_1X10:
formats += ARRAY_SIZE(tegra_camera_formats);
for (k = 0;
- xlate && (k < ARRAY_SIZE(tegra_camera_formats));
- k++) {
- xlate->host_fmt = &tegra_camera_formats[k];
- xlate->code = code;
+ xlate && (k < ARRAY_SIZE(tegra_camera_formats));
+ k++) {
+ xlate->host_fmt = &tegra_camera_formats[k];
+ xlate->code = code;
xlate++;
dev_info(dev, "Providing format %s using code %d\n",
- tegra_camera_formats[k].name, code);
+ tegra_camera_formats[k].name, code);
}
break;
default:
@@ -1522,7 +1653,7 @@ static void tegra_camera_put_formats(struct soc_camera_device *icd)
}
static int tegra_camera_set_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
+ struct v4l2_format *f)
{
struct device *dev = icd->parent;
struct soc_camera_host *ici = to_soc_camera_host(dev);
@@ -1542,28 +1673,28 @@ static int tegra_camera_set_fmt(struct soc_camera_device *icd,
return -EINVAL;
}
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf.width = pix->width;
+ mf.height = pix->height;
+ mf.field = pix->field;
+ mf.colorspace = pix->colorspace;
+ mf.code = xlate->code;
ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
if (IS_ERR_VALUE(ret)) {
dev_warn(dev, "Failed to configure for format %x\n",
- pix->pixelformat);
+ pix->pixelformat);
return ret;
}
if (mf.code != xlate->code) {
dev_warn(dev, "mf.code = %d, xlate->code = %d, mismatch\n",
- mf.code, xlate->code);
+ mf.code, xlate->code);
return -EINVAL;
}
- icd->user_width = mf.width;
- icd->user_height = mf.height;
- icd->current_fmt = xlate;
+ icd->user_width = mf.width;
+ icd->user_height = mf.height;
+ icd->current_fmt = xlate;
pcdev->field = pix->field;
@@ -1573,7 +1704,7 @@ static int tegra_camera_set_fmt(struct soc_camera_device *icd,
}
static int tegra_camera_try_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
+ struct v4l2_format *f)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
@@ -1591,62 +1722,62 @@ static int tegra_camera_try_fmt(struct soc_camera_device *icd,
}
pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
- xlate->host_fmt);
+ xlate->host_fmt);
if (pix->bytesperline < 0)
return pix->bytesperline;
pix->sizeimage = pix->height * pix->bytesperline;
/* limit to sensor capabilities */
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf.width = pix->width;
+ mf.height = pix->height;
+ mf.field = pix->field;
+ mf.colorspace = pix->colorspace;
+ mf.code = xlate->code;
ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
if (IS_ERR_VALUE(ret))
return ret;
- pix->width = mf.width;
- pix->height = mf.height;
- pix->colorspace = mf.colorspace;
+ pix->width = mf.width;
+ pix->height = mf.height;
+ pix->colorspace = mf.colorspace;
/*
* width and height could have been changed, therefore update the
* bytesperline and sizeimage here.
*/
pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
- xlate->host_fmt);
+ xlate->host_fmt);
pix->sizeimage = pix->height * pix->bytesperline;
switch (mf.field) {
case V4L2_FIELD_ANY:
case V4L2_FIELD_NONE:
- pix->field = V4L2_FIELD_NONE;
+ pix->field = V4L2_FIELD_NONE;
+ break;
+ case V4L2_FIELD_INTERLACED_BT:
+ pix->field = V4L2_FIELD_INTERLACED_BT;
+ break;
+ case V4L2_FIELD_INTERLACED_TB:
+ pix->field = V4L2_FIELD_INTERLACED_TB;
break;
- case V4L2_FIELD_INTERLACED_BT:
- pix->field = V4L2_FIELD_INTERLACED_BT;
- break;
- case V4L2_FIELD_INTERLACED_TB:
- pix->field = V4L2_FIELD_INTERLACED_TB;
- break;
case V4L2_FIELD_INTERLACED:
- pix->field = V4L2_FIELD_INTERLACED;
+ pix->field = V4L2_FIELD_INTERLACED;
break;
default:
/* TODO: support interlaced at least in pass-through mode */
dev_err(icd->parent, "Field type %d unsupported.\n",
- mf.field);
+ mf.field);
return -EINVAL;
}
dev_dbg(icd->parent,
- "Finished tegra_camera_try_fmt(), returning %d\n", ret);
+ "Finished tegra_camera_try_fmt(), returning %d\n", ret);
return ret;
}
static int tegra_camera_reqbufs(struct soc_camera_device *icd,
- struct v4l2_requestbuffers *p)
+ struct v4l2_requestbuffers *p)
{
return 0;
}
@@ -1659,7 +1790,7 @@ static unsigned int tegra_camera_poll(struct file *file, poll_table *pt)
}
static int tegra_camera_querycap(struct soc_camera_host *ici,
- struct v4l2_capability *cap)
+ struct v4l2_capability *cap)
{
strlcpy(cap->card, TEGRA_CAM_DRV_NAME, sizeof(cap->card));
cap->version = TEGRA_CAM_VERSION_CODE;
@@ -1669,23 +1800,23 @@ static int tegra_camera_querycap(struct soc_camera_host *ici,
}
static struct soc_camera_host_ops tegra_soc_camera_host_ops = {
- .owner = THIS_MODULE,
- .init_videobuf2 = tegra_camera_init_videobuf,
- .add = tegra_camera_add_device,
- .remove = tegra_camera_remove_device,
- .set_bus_param = tegra_camera_set_bus_param,
- .get_formats = tegra_camera_get_formats,
- .put_formats = tegra_camera_put_formats,
- .set_fmt = tegra_camera_set_fmt,
- .try_fmt = tegra_camera_try_fmt,
- .reqbufs = tegra_camera_reqbufs,
- .poll = tegra_camera_poll,
- .querycap = tegra_camera_querycap,
+ .owner = THIS_MODULE,
+ .init_videobuf2 = tegra_camera_init_videobuf,
+ .add = tegra_camera_add_device,
+ .remove = tegra_camera_remove_device,
+ .set_bus_param = tegra_camera_set_bus_param,
+ .get_formats = tegra_camera_get_formats,
+ .put_formats = tegra_camera_put_formats,
+ .set_fmt = tegra_camera_set_fmt,
+ .try_fmt = tegra_camera_try_fmt,
+ .reqbufs = tegra_camera_reqbufs,
+ .poll = tegra_camera_poll,
+ .querycap = tegra_camera_querycap,
};
static int __devinit tegra_camera_probe(struct nvhost_device *ndev,
- struct nvhost_device_id *id_table)
+ struct nvhost_device_id *id_table)
{
struct tegra_camera_dev *pcdev;
int err = 0;
@@ -1697,14 +1828,14 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev,
goto exit;
}
- pcdev->pdata = ndev->dev.platform_data;
- pcdev->ndev = ndev;
+ pcdev->pdata = ndev->dev.platform_data;
+ pcdev->ndev = ndev;
- pcdev->ici.priv = pcdev;
- pcdev->ici.v4l2_dev.dev = &ndev->dev;
- pcdev->ici.nr = ndev->id;
- pcdev->ici.drv_name = dev_name(&ndev->dev);
- pcdev->ici.ops = &tegra_soc_camera_host_ops;
+ pcdev->ici.priv = pcdev;
+ pcdev->ici.v4l2_dev.dev = &ndev->dev;
+ pcdev->ici.nr = ndev->id;
+ pcdev->ici.drv_name = dev_name(&ndev->dev);
+ pcdev->ici.ops = &tegra_soc_camera_host_ops;
INIT_LIST_HEAD(&pcdev->capture);
INIT_WORK(&pcdev->work, tegra_camera_work);
@@ -1715,7 +1846,7 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev,
if (!tegra_camera_port_is_valid(pcdev->pdata->port)) {
dev_err(&ndev->dev, "Invalid camera port %d in platform data\n",
- pcdev->pdata->port);
+ pcdev->pdata->port);
goto exit_free_pcdev;
}
@@ -1755,7 +1886,7 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev,
if (err)
goto exit_put_clk_csus;
- // initialize nvhost client device only the first time
+ /* initialize nvhost client device only the first time */
if (ndev->power_attrib == NULL)
nvhost_client_device_init(ndev);
@@ -1804,7 +1935,7 @@ static int __devexit tegra_camera_remove(struct nvhost_device *ndev)
{
struct soc_camera_host *ici = to_soc_camera_host(&ndev->dev);
struct tegra_camera_dev *pcdev = container_of(ici,
- struct tegra_camera_dev, ici);
+ struct tegra_camera_dev, ici);
struct resource *res;
res = nvhost_get_resource_byname(ndev, IORESOURCE_MEM, "regs");
@@ -1837,7 +1968,7 @@ static int tegra_camera_suspend(struct nvhost_device *ndev, pm_message_t state)
{
struct soc_camera_host *ici = to_soc_camera_host(&ndev->dev);
struct tegra_camera_dev *pcdev = container_of(ici,
- struct tegra_camera_dev, ici);
+ struct tegra_camera_dev, ici);
mutex_lock(&pcdev->work_mutex);
@@ -1860,7 +1991,7 @@ static int tegra_camera_resume(struct nvhost_device *ndev)
{
struct soc_camera_host *ici = to_soc_camera_host(&ndev->dev);
struct tegra_camera_dev *pcdev = container_of(ici,
- struct tegra_camera_dev, ici);
+ struct tegra_camera_dev, ici);
/* We only need to do something if a camera sensor is attached. */
if (pcdev->icd) {
@@ -1885,15 +2016,15 @@ static int tegra_camera_resume(struct nvhost_device *ndev)
#endif
static struct nvhost_driver tegra_camera_driver = {
- .driver = {
- .name = TEGRA_CAM_DRV_NAME,
- .owner = THIS_MODULE,
+ .driver = {
+ .name = TEGRA_CAM_DRV_NAME,
+ .owner = THIS_MODULE,
},
- .probe = tegra_camera_probe,
- .remove = __devexit_p(tegra_camera_remove),
+ .probe = tegra_camera_probe,
+ .remove = __devexit_p(tegra_camera_remove),
#ifdef CONFIG_PM_FISH
- .suspend = tegra_camera_suspend,
- .resume = tegra_camera_resume,
+ .suspend = tegra_camera_suspend,
+ .resume = tegra_camera_resume,
#endif
};