diff options
author | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2015-01-16 03:15:03 +0100 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2015-01-16 10:42:08 +0100 |
commit | 4e87f2dd9bc258c85b2f3bb1a100b49927fbe6f3 (patch) | |
tree | 96c82edf20e2c28e8fc4d97438d00e3b18b8afe9 | |
parent | fe4c58c4b96a24aba8e27956e8158b3002723b17 (diff) | |
parent | c7460e0d6afd754ebf5555477129579bc83c47b9 (diff) |
Merge remote-tracking branch 'remotes/nvidia/l4t/l4t-r16-r2' into tegra-next
(tegra-l4t-r16-16.5)
Conflicts:
drivers/media/video/tegra_v4l2_camera.c
drivers/mmc/host/sdhci.c
drivers/watchdog/tegra_wdt.c
include/media/tegra_v4l2_camera.h
-rw-r--r-- | arch/arm/mach-tegra/board-cardhu-sensors.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pwm.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_clocks.c | 2 | ||||
-rw-r--r-- | drivers/media/video/tegra_v4l2_camera.c | 784 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 9 | ||||
-rw-r--r-- | drivers/video/tegra/dc/hdmi.c | 5 | ||||
-rw-r--r-- | drivers/video/tegra/fb.c | 4 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_acm.c | 3 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_job.c | 9 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_syncpt.c | 1 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvmap.c | 11 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvmap.h | 5 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap.c | 16 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap_handle.c | 13 | ||||
-rw-r--r-- | drivers/watchdog/tegra_wdt.c | 9 | ||||
-rw-r--r-- | include/linux/nvmap.h | 5 | ||||
-rw-r--r-- | include/media/tegra_v4l2_camera.h | 8 |
17 files changed, 502 insertions, 399 deletions
diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c index af66e1f571c6..3c259ebcdba1 100644 --- a/arch/arm/mach-tegra/board-cardhu-sensors.c +++ b/arch/arm/mach-tegra/board-cardhu-sensors.c @@ -115,6 +115,8 @@ static struct tegra_camera_platform_data cardhu_ov5640_camera_platform_data = { .port = TEGRA_CAMERA_PORT_CSI_B, .lanes = 2, .continuous_clk = 0, + .continuous_capture = 1, + .vi_freq = 24000000, }; static struct soc_camera_link ov5640_iclink = { @@ -667,7 +669,7 @@ static const struct i2c_board_info cardhu_i2c3_board_info[] = { }, }; - +#if !defined(CONFIG_SOC_CAMERA) static struct nvc_gpio_pdata sh532u_gpio_pdata[] = { { SH532U_GPIO_RESET, TEGRA_GPIO_PBB0, false, 0, }, }; @@ -862,6 +864,7 @@ static struct i2c_board_info cardhu_i2c8_board_info[] = { }, #endif }; +#endif static int nct_get_temp(void *_data, long *temp) { @@ -1190,14 +1193,15 @@ int __init cardhu_sensors_init(void) cardhu_camera_init(); cam_tca6416_init(); + i2c_register_board_info(2, cardhu_i2c3_board_info, + ARRAY_SIZE(cardhu_i2c3_board_info)); + +#if !defined(CONFIG_SOC_CAMERA) if (board_info.board_id != BOARD_PM315) { - i2c_register_board_info(2, cardhu_i2c3_board_info, - ARRAY_SIZE(cardhu_i2c3_board_info)); i2c_register_board_info(2, cardhu_i2c_board_info_tps61050, ARRAY_SIZE(cardhu_i2c_board_info_tps61050)); } - #ifdef CONFIG_VIDEO_OV14810 /* This is disabled by default; To enable this change Kconfig; * there should be some way to detect dynamically which board @@ -1230,6 +1234,7 @@ int __init cardhu_sensors_init(void) ARRAY_SIZE(cardhu_i2c8_board_info)); #endif +#endif pmu_tca6416_init(); if (board_info.board_id == BOARD_E1291) diff --git a/arch/arm/mach-tegra/pwm.c b/arch/arm/mach-tegra/pwm.c index d5533c7d3c05..f2c43e994c9f 100644 --- a/arch/arm/mach-tegra/pwm.c +++ b/arch/arm/mach-tegra/pwm.c @@ -3,7 +3,7 @@ * * Tegra pulse-width-modulation controller driver * - * Copyright (c) 2010, NVIDIA Corporation. + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. * Based on arch/arm/plat-mxc/pwm.c by Sascha Hauer <s.hauer@pengutronix.de> * * This program is free software; you can redistribute it and/or modify @@ -131,7 +131,7 @@ void pwm_disable(struct pwm_device *pwm) clk_disable(pwm->clk); pwm->clk_enb = 0; } else - dev_warn(&pwm->pdev->dev, "%s called on disabled PWM\n", + dev_info(&pwm->pdev->dev, "%s called on disabled PWM\n", __func__); mutex_unlock(&pwm_lock); } diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c index fafa5a22157a..eaacad3d3396 100644 --- a/arch/arm/mach-tegra/tegra3_clocks.c +++ b/arch/arm/mach-tegra/tegra3_clocks.c @@ -4372,7 +4372,7 @@ struct clk tegra_list_clks[] = { PERIPH_CLK("uartc_dbg", "serial8250.0", "uartc", 55, 0x1a0, 900000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB), PERIPH_CLK("uartd_dbg", "serial8250.0", "uartd", 65, 0x1c0, 900000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB), PERIPH_CLK("uarte_dbg", "serial8250.0", "uarte", 66, 0x1c4, 900000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB), - PERIPH_CLK_EX("vi", "tegra_camera", "vi", 20, 0x148, 470000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT, &tegra_vi_clk_ops), + PERIPH_CLK_EX("vi", "tegra_camera", "vi", 20, 0x148, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71, &tegra_vi_clk_ops), PERIPH_CLK("vi_sensor", "tegra_camera", "vi_sensor", 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET), PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 600000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET), PERIPH_CLK("3d2", "3d2", NULL, 98, 0x3b0, 600000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET), diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c index 4272b34a3d56..0d50a0847383 100644 --- a/drivers/media/video/tegra_v4l2_camera.c +++ b/drivers/media/video/tegra_v4l2_camera.c @@ -22,7 +22,6 @@ #include <linux/clk.h> #include <linux/pm_runtime.h> #include <linux/nvhost.h> - #include <linux/kthread.h> #include <mach/iomap.h> @@ -31,10 +30,8 @@ #include <media/soc_camera.h> #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> +#include <media/tegra_v4l2_camera.h> #include "dev.h" #include "bus_client.h" @@ -308,9 +305,12 @@ struct tegra_camera_dev { struct work_struct work; struct mutex work_mutex; + struct soc_camera_device *icd; + u32 syncpt_vi; u32 syncpt_csi_a; u32 syncpt_csi_b; + int capturing; /* private buffer for non-interlaced frame */ struct vb2_dc_buf *internal_vbuf; @@ -437,27 +437,27 @@ static void tegra_camera_save_syncpts(struct tegra_camera_dev *pcdev) { pcdev->syncpt_csi_a = nvhost_syncpt_read_ext(pcdev->ndev, - TEGRA_VI_SYNCPT_CSI_A); + TEGRA_VI_SYNCPT_CSI_A); pcdev->syncpt_csi_b = nvhost_syncpt_read_ext(pcdev->ndev, - TEGRA_VI_SYNCPT_CSI_B); + TEGRA_VI_SYNCPT_CSI_B); 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_A); + TEGRA_VI_SYNCPT_CSI_A); nvhost_syncpt_cpu_incr_ext(pcdev->ndev, - TEGRA_VI_SYNCPT_CSI_B); + TEGRA_VI_SYNCPT_CSI_B); nvhost_syncpt_cpu_incr_ext(pcdev->ndev, - TEGRA_VI_SYNCPT_VI); + TEGRA_VI_SYNCPT_VI); } static void tegra_camera_capture_clean(struct tegra_camera_dev *pcdev) @@ -484,8 +484,8 @@ static void tegra_camera_capture_clean(struct tegra_camera_dev *pcdev) } static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, - struct soc_camera_device *icd, - u32 hdr) + struct soc_camera_device *icd, + u32 hdr) { struct tegra_camera_platform_data *pdata = icd->link->priv; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, @@ -507,43 +507,43 @@ static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, /* CSI-A H_ACTIVE and V_ACTIVE */ TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_H_ACTIVE, - (icd->user_width << 16)); + (icd->user_width << 16)); TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_V_ACTIVE, - (icd->user_height << 16)); + (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 */ + (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 */ - (pdata->lanes - 1)); + (0x3f << 16) | /* Skip packet threshold */ + (pdata->lanes - 1)); /* Use 0x00000022 for continuous clock mode. */ TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILA_CONTROL0, - (pdata->continuous_clk << 5) | - 0x5); /* Clock settle time */ + (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_A); + TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_START, + (0x1 << 8) | /* Enable continuous syncpt */ + TEGRA_VI_SYNCPT_CSI_A); TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00020001); @@ -551,12 +551,12 @@ 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, - struct soc_camera_device *icd, - u32 hdr) + struct soc_camera_device *icd, + u32 hdr) { struct tegra_camera_platform_data *pdata = icd->link->priv; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, - icd->current_fmt->host_fmt); + icd->current_fmt->host_fmt); TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_B_CONTROL, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, 0x00000000); @@ -574,44 +574,44 @@ static void tegra_camera_capture_setup_csi_b(struct tegra_camera_dev *pcdev, /* 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)); + (icd->user_height << 16)); /* 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 */ - (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 */ + (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 */ - (pdata->lanes - 1)); + (0x3f << 16) | /* Skip packet threshold */ + (pdata->lanes - 1)); /* Use 0x00000022 for continuous clock mode. */ TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILB_CONTROL0, - (pdata->continuous_clk << 5) | - 0x5); /* Clock settle time */ + (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_B); + TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_START, + (0x1 << 8) | /* Enable continuous syncpt */ + TEGRA_VI_SYNCPT_CSI_B); TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00010002); @@ -619,32 +619,33 @@ 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, - struct soc_camera_device *icd, - u32 input_control) + struct soc_camera_device *icd, + u32 input_control) { struct tegra_camera_platform_data *pdata = icd->link->priv; 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 */ - (((pdata->internal_sync == true) ? 1 : 0) << 25) | /* 1 == hsync/vsync decoded - internally from data - (BT.656) */ - (1 << 1) | /* VIP_INPUT_ENABLE */ - input_control); + /* (1 << 27) | field detect */ + (0 << 28) | /* 1 == top field is even field, 00 == odd */ + (((pdata->internal_sync == true) ? 1 : 0) << 25) | + /* 1 == hsync/vsync decoded + internally from data + (BT.656) */ + (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) | - (pdata->vip_h_active_start - ((pdata->internal_sync == true) ? 1 : 0))); + (icd->user_width << 16) | + (pdata->vip_h_active_start - ((pdata->internal_sync == true) ? 1 : 0))); TC_VI_REG_WT(pcdev, TEGRA_VI_VIP_V_ACTIVE, - ((IS_INTERLACED ? (icd->user_height/2) : (icd->user_height)) << 16) | - pdata->vip_v_active_start); + ((IS_INTERLACED ? (icd->user_height/2) : (icd->user_height)) << 16) | + pdata->vip_v_active_start); /* * For VIP, D9..D2 is mapped to the video decoder's P7..P0. @@ -655,10 +656,10 @@ static void tegra_camera_capture_setup_vip(struct tegra_camera_dev *pcdev, 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 { @@ -680,7 +681,7 @@ static int tegra_camera_capture_output_channel_setup( struct tegra_camera_platform_data *pdata = icd->link->priv; int port = pdata->port; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, - icd->current_fmt->host_fmt); + icd->current_fmt->host_fmt); const struct soc_camera_format_xlate *current_fmt = icd->current_fmt; u32 output_fourcc = current_fmt->host_fmt->fourcc; u32 output_format, output_control; @@ -688,43 +689,43 @@ static int tegra_camera_capture_output_channel_setup( struct tegra_buffer *buf = to_tegra_vb(pcdev->active); switch (output_fourcc) { - case V4L2_PIX_FMT_UYVY: - output_format = 0x3; /* Default to YUV422 */ - break; - case V4L2_PIX_FMT_VYUY: - output_format = (0x1 << 17) | 0x3; - break; - case V4L2_PIX_FMT_YUYV: - output_format = (0x2 << 17) | 0x3; - break; - case V4L2_PIX_FMT_YVYU: - 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 */ - buf->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: - dev_err(&pcdev->ndev->dev, "Wrong output format %d\n", - output_fourcc); - return -EINVAL; + case V4L2_PIX_FMT_UYVY: + output_format = 0x3; /* Default to YUV422 */ + break; + case V4L2_PIX_FMT_VYUY: + output_format = (0x1 << 17) | 0x3; + break; + case V4L2_PIX_FMT_YUYV: + output_format = (0x2 << 17) | 0x3; + break; + case V4L2_PIX_FMT_YVYU: + 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 */ + buf->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: + dev_err(&pcdev->ndev->dev, "Wrong output format %d\n", + output_fourcc); + return -EINVAL; } output_control = (pdata->flip_v ? (0x1 << 20) : 0) | - (pdata->flip_h ? (0x1 << 19) : 0) | - output_format; + (pdata->flip_h ? (0x1 << 19) : 0) | + output_format; /* if the video is interlaced, then take two frames */ frame_count = IS_INTERLACED ? 2 : 1; @@ -788,7 +789,7 @@ static int tegra_camera_capture_output_channel_setup( TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE_2, 0x00000000); } else { dev_err(&pcdev->ndev->dev, "Wrong output channel %d\n", - buf->output_channel); + buf->output_channel); return -EINVAL; } @@ -805,35 +806,39 @@ static int tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) const struct soc_camera_format_xlate *current_fmt = icd->current_fmt; enum v4l2_mbus_pixelcode input_code = current_fmt->code; u32 hdr, input_control = 0x0; + + if (!pcdev->icd) + pcdev->icd = icd; + switch (input_code) { - case V4L2_MBUS_FMT_UYVY8_2X8: - input_control |= 0x2 << 8; - hdr = 30; - break; - case V4L2_MBUS_FMT_VYUY8_2X8: - input_control |= 0x3 << 8; - hdr = 30; - break; - case V4L2_MBUS_FMT_YUYV8_2X8: - input_control |= 0x0; - hdr = 30; - break; - case V4L2_MBUS_FMT_YVYU8_2X8: - input_control |= 0x1 << 8; - hdr = 30; - break; - case V4L2_MBUS_FMT_SBGGR8_1X8: - input_control |= 0x2 << 2; /* Input Format = Bayer */ - hdr = 42; - break; - case V4L2_MBUS_FMT_SBGGR10_1X10: - input_control |= 0x2 << 2; /* Input Format = Bayer */ - hdr = 43; - break; - default: - dev_err(&pcdev->ndev->dev, "Input format %d is not supported\n", - input_code); - return -EINVAL; + case V4L2_MBUS_FMT_UYVY8_2X8: + input_control |= 0x2 << 8; + hdr = 30; + break; + case V4L2_MBUS_FMT_VYUY8_2X8: + input_control |= 0x3 << 8; + hdr = 30; + break; + case V4L2_MBUS_FMT_YUYV8_2X8: + input_control |= 0x0; + hdr = 30; + break; + case V4L2_MBUS_FMT_YVYU8_2X8: + input_control |= 0x1 << 8; + hdr = 30; + break; + case V4L2_MBUS_FMT_SBGGR8_1X8: + input_control |= 0x2 << 2; /* Input Format = Bayer */ + hdr = 42; + break; + case V4L2_MBUS_FMT_SBGGR10_1X10: + input_control |= 0x2 << 2; /* Input Format = Bayer */ + hdr = 43; + break; + default: + dev_err(&pcdev->ndev->dev, "Input format %d is not supported\n", + input_code); + return -EINVAL; } /* @@ -846,8 +851,10 @@ static int 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); + if (!pdata->continuous_capture || !pcdev->capturing) { + /* Cleanup registers */ + tegra_camera_capture_clean(pcdev); + } /* Setup registers for CSI-A, CSI-B and VIP inputs */ if (port == TEGRA_CAMERA_PORT_CSI_A) @@ -862,59 +869,59 @@ static int tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) } static int tegra_camera_capture_buffer_setup(struct tegra_camera_dev *pcdev, - struct tegra_buffer *buf) + struct tegra_buffer *buf) { struct soc_camera_device *icd = buf->icd; 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); - TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_U, - buf->start_addr_u); - - TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_V, - buf->buffer_addr_v); - TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_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: - case V4L2_PIX_FMT_SGRBG8: - case V4L2_PIX_FMT_SGRBG10: - /* output 1 */ - if (buf->output_channel == 0) { - 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 (buf->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); - } else { - dev_err(&pcdev->ndev->dev, "Wrong output channel %d\n", - buf->output_channel); - return -EINVAL; - } - break; - - default: - dev_err(&pcdev->ndev->dev, "Wrong host format %d\n", - 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); + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_U, + buf->start_addr_u); + + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_V, + buf->buffer_addr_v); + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_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: + case V4L2_PIX_FMT_SGRBG8: + case V4L2_PIX_FMT_SGRBG10: + /* output 1 */ + if (buf->output_channel == 0) { + 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 (buf->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); + } else { + dev_err(&pcdev->ndev->dev, "Wrong output channel %d\n", + buf->output_channel); return -EINVAL; + } + break; + + default: + dev_err(&pcdev->ndev->dev, "Wrong host format %d\n", + icd->current_fmt->host_fmt->fourcc); + return -EINVAL; } return 0; } static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, - struct tegra_buffer *buf) + struct tegra_buffer *buf) { struct soc_camera_device *icd = buf->icd; struct tegra_camera_platform_data *pdata = icd->link->priv; @@ -932,18 +939,22 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, * wait on VIP VSYNC syncpt. */ if (port == TEGRA_CAMERA_PORT_CSI_A) { - pcdev->syncpt_csi_a++; + pcdev->syncpt_csi_a = nvhost_syncpt_incr_max_ext(pcdev->ndev, + TEGRA_VI_SYNCPT_CSI_A, 1); TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, - 0x0000f005); + pdata->continuous_capture?0x0000f001 :0x0000f005); + err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev, TEGRA_VI_SYNCPT_CSI_A, pcdev->syncpt_csi_a, TEGRA_SYNCPT_CSI_WAIT_TIMEOUT, NULL); } else if (port == TEGRA_CAMERA_PORT_CSI_B) { - pcdev->syncpt_csi_b++; + pcdev->syncpt_csi_b = nvhost_syncpt_incr_max_ext(pcdev->ndev, + TEGRA_VI_SYNCPT_CSI_B, 1); TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, - 0x0000f005); + pdata->continuous_capture? 0x0000f001: 0x0000f005); + err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev, TEGRA_VI_SYNCPT_CSI_B, pcdev->syncpt_csi_b, @@ -957,9 +968,10 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, interlace_task = kthread_run(make_interlaced, &ta, "interlacing thread"); } while (count-- && !err) { - pcdev->syncpt_vi++; + pcdev->syncpt_vi = nvhost_syncpt_incr_max_ext(pcdev->ndev, + TEGRA_VI_SYNCPT_VI, 1); TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL, - 0x00000005); + pdata->continuous_capture? 0x00000001: 0x00000005); err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev, TEGRA_VI_SYNCPT_VI, pcdev->syncpt_vi, @@ -968,6 +980,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, } } + pcdev->capturing = 1; + if (!err) return 0; @@ -978,34 +992,35 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, dev_warn(&icd->vdev->dev, "Timeout on CSI syncpt\n"); dev_warn(&icd->vdev->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_warn(&icd->vdev->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_warn(&pcdev->ndev->dev, "Timeout on VI syncpt\n"); dev_warn(&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_warn(&pcdev->ndev->dev, - "VIP_INPUT_STATUS = 0x%08x\n", - vip_input_status); + "VIP_INPUT_STATUS = 0x%08x\n", + vip_input_status); } + return err; } @@ -1016,20 +1031,22 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev, int port) 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); */ + /* pcdev->syncpt_vi = nvhost_syncpt_incr_max_ext(pcdev->ndev, */ + /* TEGRA_VI_SYNCPT_VI, 1); */ 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; @@ -1042,26 +1059,26 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev, int port) if (buf->output_channel == 0) buffer_addr = TC_VI_REG_RD(pcdev, - TEGRA_VI_VB0_BASE_ADDRESS_FIRST); + TEGRA_VI_VB0_BASE_ADDRESS_FIRST); else if (buf->output_channel == 1) buffer_addr = TC_VI_REG_RD(pcdev, - TEGRA_VI_VB0_BASE_ADDRESS_SECOND); + TEGRA_VI_VB0_BASE_ADDRESS_SECOND); else { dev_err(&pcdev->ndev->dev, "Wrong output channel %d\n", - buf->output_channel); + buf->output_channel); return -EINVAL; } dev_warn(&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_warn(&pcdev->ndev->dev, - "PPSTATUS = 0x%08x, CILSTATUS = 0x%08x\n", - ppstatus, cilstatus); + "PPSTATUS = 0x%08x, CILSTATUS = 0x%08x\n", + ppstatus, cilstatus); } return err; @@ -1083,7 +1100,7 @@ static void tegra_camera_activate(struct tegra_camera_dev *pcdev) tegra_unpowergate_partition(TEGRA_POWERGATE_VENC); /* Turn on relevant clocks. */ - clk_set_rate(pcdev->clk_vi, 150000000); + clk_set_rate(pcdev->clk_vi, 300000000); clk_enable(pcdev->clk_vi); clk_set_rate(pcdev->clk_vi_sensor, 24000000); clk_enable(pcdev->clk_vi_sensor); @@ -1092,7 +1109,6 @@ static void tegra_camera_activate(struct tegra_camera_dev *pcdev) clk_enable(pcdev->clk_csus); clk_set_rate(pcdev->clk_sclk, 80000000); clk_enable(pcdev->clk_sclk); - clk_set_rate(pcdev->clk_sclk, 375000000); clk_enable(pcdev->clk_emc); #ifdef CONFIG_ARCH_TEGRA_2x_SOC @@ -1107,6 +1123,20 @@ static void tegra_camera_activate(struct tegra_camera_dev *pcdev) static void tegra_camera_deactivate(struct tegra_camera_dev *pcdev) { + struct soc_camera_device *icd = pcdev->icd; + if (icd) { + struct tegra_camera_platform_data *pdata = icd->link->priv; + + if (pdata->continuous_capture) { + pcdev->capturing = 0; + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, + 0x0000f003); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, + 0x0000f003); + usleep_range(20000, 21000); + } + } + /* Turn off relevant clocks. */ clk_disable(pcdev->clk_vi); clk_disable(pcdev->clk_vi_sensor); @@ -1136,6 +1166,7 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev) int port = pdata->port; int retry = TEGRA_SYNCPT_RETRY_COUNT; int err; + while (retry) { err = tegra_camera_capture_start(pcdev, buf); /* Capturing succeed, stop capturing */ @@ -1148,30 +1179,30 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev) /* 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); @@ -1179,8 +1210,10 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev) continue; } + break; } + /* Reset hardware for too many errors */ if (!retry) { tegra_camera_deactivate(pcdev); @@ -1197,6 +1230,7 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev) } spin_lock_irq(&pcdev->videobuf_queue_lock); + do_gettimeofday(&vb->v4l2_buf.timestamp); vb->v4l2_buf.field = pcdev->field; if (port == TEGRA_CAMERA_PORT_CSI_A) @@ -1297,6 +1331,8 @@ static void tegra_camera_work(struct work_struct *work) struct tegra_camera_dev *pcdev = container_of(work, struct tegra_camera_dev, work); struct tegra_buffer *buf; + struct soc_camera_device *icd; + struct tegra_camera_platform_data *pdata; while (1) { mutex_lock(&pcdev->work_mutex); @@ -1314,10 +1350,15 @@ static void tegra_camera_work(struct work_struct *work) pcdev->active = &buf->vb; spin_unlock_irq(&pcdev->videobuf_queue_lock); - tegra_camera_capture_setup(pcdev); - if (!pcdev->cal_done) { - tegra_camera_csi_pad_calibration(pcdev); - pcdev->cal_done = 1; + icd = buf->icd; + pdata = icd->link->priv; + + if (!pdata->continuous_capture || !pcdev->capturing) { + tegra_camera_capture_setup(pcdev); + if (!pcdev->cal_done) { + tegra_camera_csi_pad_calibration(pcdev); + pcdev->cal_done = 1; + } } tegra_camera_capture_frame(pcdev); @@ -1329,7 +1370,7 @@ static int tegra_camera_init_buffer(struct tegra_buffer *buf) { struct soc_camera_device *icd = buf->icd; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, - icd->current_fmt->host_fmt); + icd->current_fmt->host_fmt); struct tegra_camera_platform_data *pdata = icd->link->priv; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); @@ -1343,66 +1384,66 @@ static int tegra_camera_init_buffer(struct tegra_buffer *buf) 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; + 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 (pdata->flip_v) - buf->start_addr += bytes_per_line * - (icd->user_height-1); + if (pdata->flip_v) + buf->start_addr += bytes_per_line * + (icd->user_height-1); - if (pdata->flip_h) - buf->start_addr += bytes_per_line - 1; + if (pdata->flip_h) + buf->start_addr += bytes_per_line - 1; - break; + break; - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YVU420: - buf->buffer_addr_u = buf->buffer_addr + - icd->user_width * icd->user_height; - buf->buffer_addr_v = buf->buffer_addr_u + - (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) { - dma_addr_t temp = buf->buffer_addr_u; - buf->buffer_addr_u = buf->buffer_addr_v; - buf->buffer_addr_v = temp; - } + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + buf->buffer_addr_u = buf->buffer_addr + + icd->user_width * icd->user_height; + buf->buffer_addr_v = buf->buffer_addr_u + + (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) { + dma_addr_t temp = buf->buffer_addr_u; + buf->buffer_addr_u = buf->buffer_addr_v; + buf->buffer_addr_v = temp; + } - buf->start_addr = buf->buffer_addr; - buf->start_addr_u = buf->buffer_addr_u; - buf->start_addr_v = buf->buffer_addr_v; + buf->start_addr = buf->buffer_addr; + buf->start_addr_u = buf->buffer_addr_u; + buf->start_addr_v = buf->buffer_addr_v; - if (pdata->flip_v) { - buf->start_addr += icd->user_width * - (icd->user_height - 1); + if (pdata->flip_v) { + buf->start_addr += icd->user_width * + (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 (pdata->flip_h) { - buf->start_addr += icd->user_width - 1; + if (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; + break; - default: - dev_err(icd->parent, "Wrong host format %d\n", - icd->current_fmt->host_fmt->fourcc); - return -EINVAL; + default: + dev_err(icd->parent, "Wrong host format %d\n", + icd->current_fmt->host_fmt->fourcc); + return -EINVAL; } return 0; @@ -1412,19 +1453,19 @@ static int tegra_camera_init_buffer(struct tegra_buffer *buf) * 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 tegra_camera_platform_data *pdata = icd->link->priv; 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"); @@ -1432,6 +1473,7 @@ static int tegra_camera_videobuf_setup(struct vb2_queue *vq, return bytes_per_line; *num_planes = 1; + if (pdata->port == TEGRA_CAMERA_PORT_CSI_A) pcdev->sequence_a = 0; else if (pdata->port == TEGRA_CAMERA_PORT_CSI_B) @@ -1451,12 +1493,12 @@ 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 tegra_buffer *buf = to_tegra_vb(vb); struct tegra_camera_platform_data *pdata = icd->link->priv; 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"); @@ -1473,13 +1515,13 @@ static int tegra_camera_videobuf_prepare(struct vb2_buffer *vb) if (!tegra_camera_port_is_valid(pdata->port)) { dev_err(icd->parent, - "Invalid camera port %d in platform data\n", - pdata->port); + "Invalid camera port %d in platform data\n", + pdata->port); return -EINVAL; } 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 /* @@ -1499,7 +1541,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; } @@ -1511,14 +1553,14 @@ 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); 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); @@ -1531,8 +1573,8 @@ 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; @@ -1569,14 +1611,15 @@ static int tegra_camera_videobuf_init(struct vb2_buffer *vb) { /* This is for locking debugging only */ INIT_LIST_HEAD(&to_tegra_vb(vb)->queue); + return 0; } 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; @@ -1620,7 +1663,7 @@ static struct vb2_ops tegra_camera_videobuf_ops = { * 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"); @@ -1652,7 +1695,7 @@ static int tegra_camera_add_device(struct soc_camera_device *icd) pcdev->enable_refcnt++; dev_dbg(icd->parent, "TEGRA Camera host attached to camera %d\n", - icd->devnum); + icd->devnum); return 0; } @@ -1673,18 +1716,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; @@ -1706,27 +1749,27 @@ static int tegra_camera_get_formats(struct soc_camera_device *icd, } switch (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: - 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++; - - dev_info(dev, "Providing format %s using code %d\n", - tegra_camera_formats[k].name, code); - } - break; - default: - dev_info(dev, "Not supporting %s\n", fmt->name); - return 0; + case V4L2_MBUS_FMT_UYVY8_2X8: + 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++; + + dev_info(dev, "Providing format %s using code %d\n", + tegra_camera_formats[k].name, code); + } + break; + default: + dev_info(dev, "Not supporting %s\n", fmt->name); + return 0; } return formats; @@ -1739,7 +1782,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); @@ -1768,13 +1811,13 @@ static int tegra_camera_set_fmt(struct soc_camera_device *icd, 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; } @@ -1789,8 +1832,20 @@ static int tegra_camera_set_fmt(struct soc_camera_device *icd, return ret; } +static int tegra_camera_enum_fsizes(struct soc_camera_device *icd, struct v4l2_frmsizeenum * fsize) { + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + int ret; + + //printk("%s (%d)\n", __func__, fsize->index); + ret = v4l2_subdev_call(sd, video, enum_framesizes, fsize); + if (IS_ERR_VALUE(ret)) + return ret; + + return 0; +} + 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; @@ -1808,7 +1863,7 @@ 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; @@ -1832,38 +1887,38 @@ static int tegra_camera_try_fmt(struct soc_camera_device *icd, * 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; - 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; - break; - default: - /* TODO: support interlaced at least in pass-through mode */ - dev_err(icd->parent, "Field type %d unsupported.\n", - mf.field); - return -EINVAL; + case V4L2_FIELD_ANY: + case 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: + 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); + 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; } @@ -1876,7 +1931,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; @@ -1898,11 +1953,11 @@ static struct soc_camera_host_ops tegra_soc_camera_host_ops = { .reqbufs = tegra_camera_reqbufs, .poll = tegra_camera_poll, .querycap = tegra_camera_querycap, + .enum_fsizes = tegra_camera_enum_fsizes, }; - 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; @@ -1969,7 +2024,7 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev, goto exit_put_clk_sclk; } - clk_set_rate(pcdev->clk_vi, 150000000); + clk_set_rate(pcdev->clk_vi, 300000000); clk_set_rate(pcdev->clk_vi_sensor, 24000000); /* Get regulator pointer */ @@ -2053,7 +2108,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"); @@ -2088,7 +2143,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); @@ -2106,7 +2161,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) { @@ -2155,5 +2210,6 @@ module_exit(tegra_camera_exit); MODULE_DESCRIPTION("TEGRA SoC Camera Host driver"); MODULE_AUTHOR("Andrew Chew <achew@nvidia.com>"); +MODULE_AUTHOR("Bryan Wu <pengw@nvidia.com>"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("nvhost:" TEGRA_CAM_DRV_NAME); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index da1547ffc9da..7c6ff939a823 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2664,10 +2664,11 @@ int sdhci_add_host(struct sdhci_host *host) if (host->quirks & SDHCI_QUIRK2_NO_1_8_V) caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); - else - /* UHS-I mode(s) supported by the host controller. */ - if (host->version >= SDHCI_SPEC_300) - mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; + + /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ + if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | + SDHCI_SUPPORT_DDR50)) + mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; /* SDR104 supports also implies SDR50 support */ if (caps[1] & SDHCI_SUPPORT_SDR104) diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c index e5e6fff7eb46..85a5d63e9326 100644 --- a/drivers/video/tegra/dc/hdmi.c +++ b/drivers/video/tegra/dc/hdmi.c @@ -4,7 +4,7 @@ * Copyright (C) 2010 Google, Inc. * Author: Erik Gilling <konkers@android.com> * - * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION, All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -1262,7 +1262,8 @@ static bool tegra_dc_hdmi_valid_asp_ratio(const struct tegra_dc *dc, return false; /* To check the aspect upto two decimal digits, calculate in % */ - m_aspratio = (mode->xres*100 / mode->yres); + if (mode->yres) + m_aspratio = (mode->xres*100 / mode->yres); if ((m_aspratio < TEGRA_DC_HDMI_MIN_ASPECT_RATIO_PERCENT) || (m_aspratio > TEGRA_DC_HDMI_MAX_ASPECT_RATIO_PERCENT)) diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index 9d6f15cda48b..d0e7809cd83d 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -6,7 +6,7 @@ * Colin Cross <ccross@android.com> * Travis Geiselbrecht <travis@palm.com> * - * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION, All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -274,6 +274,8 @@ static int tegra_fb_blank(int blank, struct fb_info *info) dev_dbg(&tegra_fb->ndev->dev, "unblank\n"); tegra_fb->win->flags = TEGRA_WIN_FLAG_ENABLED; tegra_dc_enable(tegra_fb->win->dc); + tegra_dc_update_windows(&tegra_fb->win, 1); + tegra_dc_sync_windows(&tegra_fb->win, 1); return 0; case FB_BLANK_NORMAL: diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c index f22c91ac03f1..860ce6b35572 100644 --- a/drivers/video/tegra/host/nvhost_acm.c +++ b/drivers/video/tegra/host/nvhost_acm.c @@ -3,7 +3,7 @@ * * Tegra Graphics Host Automatic Clock Management * - * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2010-2014, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -221,6 +221,7 @@ void nvhost_module_busy(struct nvhost_device *dev) dev->refcount++; if (dev->refcount > 0 && !nvhost_module_powered(dev)) to_state_running_locked(dev); + mutex_unlock(&dev->lock); } diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c index f0f7e64d4504..5587f51ea996 100644 --- a/drivers/video/tegra/host/nvhost_job.c +++ b/drivers/video/tegra/host/nvhost_job.c @@ -3,7 +3,7 @@ * * Tegra Graphics Host Job * - * Copyright (c) 2010-2012, NVIDIA Corporation. + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -30,6 +30,7 @@ #include "dev.h" #include "nvhost_memmgr.h" #include "chip_support.h" +#include "nvmap.h" /* Magic to use to fill freed handle slots */ #define BAD_MAGIC 0xdeadbeef @@ -327,8 +328,10 @@ void nvhost_job_unpin(struct nvhost_job *job) int i; for (i = 0; i < job->num_unpins; i++) { - mem_op().unpin(job->memmgr, job->unpins[i]); - mem_op().put(job->memmgr, job->unpins[i]); + struct mem_handle *handle; + handle = nvhost_nvmap_validate_ref(job->memmgr, job->unpins[i]); + mem_op().unpin(job->memmgr, handle); + mem_op().put(job->memmgr, handle); } memset(job->unpins, BAD_MAGIC, diff --git a/drivers/video/tegra/host/nvhost_syncpt.c b/drivers/video/tegra/host/nvhost_syncpt.c index de3e04f65cdd..5837a3f76cf0 100644 --- a/drivers/video/tegra/host/nvhost_syncpt.c +++ b/drivers/video/tegra/host/nvhost_syncpt.c @@ -487,6 +487,7 @@ u32 nvhost_syncpt_incr_max_ext(struct nvhost_device *dev, u32 id, u32 incrs) struct nvhost_syncpt *sp = &(nvhost_get_host(dev)->syncpt); return nvhost_syncpt_incr_max(sp, id, incrs); } +EXPORT_SYMBOL(nvhost_syncpt_incr_max_ext); void nvhost_syncpt_cpu_incr_ext(struct nvhost_device *dev, u32 id) { diff --git a/drivers/video/tegra/host/nvmap.c b/drivers/video/tegra/host/nvmap.c index fd82f40c59ff..b8361c4a1a36 100644 --- a/drivers/video/tegra/host/nvmap.c +++ b/drivers/video/tegra/host/nvmap.c @@ -3,7 +3,7 @@ * * Tegra Graphics Host Nvmap support * - * Copyright (c) 2012, NVIDIA Corporation. + * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -82,6 +82,15 @@ struct mem_handle *nvhost_nvmap_get(struct mem_mgr *mgr, u32 id) nvmap_duplicate_handle_id((struct nvmap_client *)mgr, id); } +struct mem_handle *nvhost_nvmap_validate_ref(struct mem_mgr *mgr, + struct mem_handle *handle) +{ + unsigned long ref; + ref = nvmap_validate_ref((struct nvmap_client *)mgr, + (struct nvmap_handle_ref *)handle); + return (struct mem_handle *)ref; +} + int nvhost_init_nvmap_support(struct nvhost_chip_support *chip) { chip->mem.alloc_mgr = nvhost_nvmap_alloc_mgr; diff --git a/drivers/video/tegra/host/nvmap.h b/drivers/video/tegra/host/nvmap.h index 90f64d44f434..25e3535ce544 100644 --- a/drivers/video/tegra/host/nvmap.h +++ b/drivers/video/tegra/host/nvmap.h @@ -3,7 +3,7 @@ * * Tegra Graphics Host nvmap memory manager * - * Copyright (c) 2010-2012, NVIDIA Corporation. + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -23,5 +23,6 @@ struct nvhost_chip_support; int nvhost_init_nvmap_support(struct nvhost_chip_support *op); - +struct mem_handle *nvhost_nvmap_validate_ref(struct mem_mgr *mgr, + struct mem_handle *handle); #endif diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c index e66ca982f2f3..3329153b2c1b 100644 --- a/drivers/video/tegra/nvmap/nvmap.c +++ b/drivers/video/tegra/nvmap/nvmap.c @@ -3,7 +3,7 @@ * * Memory manager for Tegra GPU * - * Copyright (c) 2009-2012, NVIDIA Corporation. + * Copyright (c) 2009-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -366,7 +366,6 @@ phys_addr_t nvmap_pin(struct nvmap_client *client, h = nvmap_handle_get(ref->handle); if (WARN_ON(!h)) return -EINVAL; - atomic_inc(&ref->pin); if (WARN_ON(mutex_lock_interruptible(&client->share->pin_lock))) { @@ -384,7 +383,6 @@ phys_addr_t nvmap_pin(struct nvmap_client *client, map_iovmm_area(h); phys = handle_phys(h); } - return ret ?: phys; } EXPORT_SYMBOL(nvmap_pin); @@ -624,3 +622,15 @@ int nvmap_mark_global(struct nvmap_client *client, struct nvmap_handle_ref *r) return 0; } + +unsigned long nvmap_validate_ref(struct nvmap_client *client, + struct nvmap_handle_ref *r) +{ + struct nvmap_handle_ref *ref; + unsigned long id = nvmap_ref_to_id(r); + + nvmap_ref_lock(client); + ref = _nvmap_validate_id_locked(client, id); + nvmap_ref_unlock(client); + return (unsigned long)ref; +} diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c index c1add8383e83..d1d5f267f5c5 100644 --- a/drivers/video/tegra/nvmap/nvmap_handle.c +++ b/drivers/video/tegra/nvmap/nvmap_handle.c @@ -3,7 +3,7 @@ * * Handle allocation and freeing routines for nvmap * - * Copyright (c) 2009-2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2009-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -905,7 +905,7 @@ void nvmap_free_handle_id(struct nvmap_client *client, unsigned long id) nvmap_err(client, "%s freeing pinned handle %p\n", current->group_leader->comm, h); - while (pins--) + while (pins-- > 0) nvmap_unpin_handles(client, &ref->handle, 1); if (h->owner == client) @@ -989,6 +989,15 @@ struct nvmap_handle_ref *nvmap_duplicate_handle_id(struct nvmap_client *client, BUG_ON(!client || client->dev != nvmap_dev); /* on success, the reference count for the handle should be * incremented, so the success paths will not call nvmap_handle_put */ + + /* Allow the handle to be accessed by other (non-owner) + clients only if the owner is "videobuf2-dma-nvmap + which is a V4L2 capture kernel module. This handle can + be accessed by the "user" client for rendering/encoding */ + if (!strcmp(((struct nvmap_handle *)id)->owner->name, + "videobuf2-dma-nvmap")) + client = ((struct nvmap_handle *)id)->owner; + h = nvmap_validate_get(client, id); if (!h) { diff --git a/drivers/watchdog/tegra_wdt.c b/drivers/watchdog/tegra_wdt.c index d32c516b2c55..3e58a984d9c2 100644 --- a/drivers/watchdog/tegra_wdt.c +++ b/drivers/watchdog/tegra_wdt.c @@ -3,7 +3,7 @@ * * watchdog driver for NVIDIA tegra internal watchdog * - * Copyright (c) 2012, NVIDIA Corporation. + * Copyright (c) 2012-2014, NVIDIA Corporation. All rights reserved. * Copyright (c) 2013, Toradex AG * * based on drivers/watchdog/softdog.c and drivers/watchdog/omap_wdt.c @@ -264,8 +264,7 @@ static irqreturn_t tegra_wdt_interrupt(int irq, void *dev_id) continue; status = readl(wdt->wdt_source + WDT_STATUS); if ((wdt->status & WDT_ENABLED) && - (status & WDT_INTR_STAT)) - { + (status & WDT_INTR_STAT)) { tegra_wdt_interrupt_instance(wdt); } } @@ -390,10 +389,10 @@ static ssize_t tegra_wdt_write(struct file *file, const char __user *data, /* check if way-out char was written as last data */ char c; - if(len) { + if (len) { tegra_wdt_ping(wdt); - if(get_user(c, data + len - 1)) + if (get_user(c, data + len - 1)) return -EFAULT; else wdt->way_out_ok = (('V' == c) ? 1 : 0); diff --git a/include/linux/nvmap.h b/include/linux/nvmap.h index 9cc978ec5a7f..c805f4c1dc07 100644 --- a/include/linux/nvmap.h +++ b/include/linux/nvmap.h @@ -3,7 +3,7 @@ * * structure declarations for nvmem and nvmap user-space ioctls * - * Copyright (c) 2009-2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2009-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -126,6 +126,9 @@ struct nvmap_handle_ref *nvmap_duplicate_handle_id(struct nvmap_client *client, int nvmap_mark_global(struct nvmap_client *client, struct nvmap_handle_ref *r); +unsigned long nvmap_validate_ref(struct nvmap_client *client, + struct nvmap_handle_ref *r); + struct nvmap_platform_carveout { const char *name; unsigned int usage_mask; diff --git a/include/media/tegra_v4l2_camera.h b/include/media/tegra_v4l2_camera.h index fef8a9bb5db0..9f04425d6a26 100644 --- a/include/media/tegra_v4l2_camera.h +++ b/include/media/tegra_v4l2_camera.h @@ -36,10 +36,12 @@ struct tegra_camera_platform_data { int lanes; /* For CSI port only */ bool continuous_clk; /* For CSI port only */ - bool internal_sync; /* VIP */ - u8 vip_h_active_start; /* VIP */ - u8 vip_v_active_start; /* VIP */ + bool internal_sync; /* VIP */ + u8 vip_h_active_start; /* VIP */ + u8 vip_v_active_start; /* VIP */ + bool continuous_capture; /* CSI only */ + int vi_freq; }; #endif /* _TEGRA_CAMERA_H_ */ |