summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/s5p-fimc/mipi-csis.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-12 12:39:17 +0900
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-12 12:39:17 +0900
commit4f1cd91497774488ed16119ec3f54b3daf1561de (patch)
tree190ed2b2ecbbfe371740cf6e29d9aefd25ecc3e3 /drivers/media/platform/s5p-fimc/mipi-csis.c
parent759e00b8a8883be28357426206d2f1752827e38a (diff)
parentbf3b202b41999f88f091632f13842b7234bd58b7 (diff)
downloadop-kernel-dev-4f1cd91497774488ed16119ec3f54b3daf1561de.zip
op-kernel-dev-4f1cd91497774488ed16119ec3f54b3daf1561de.tar.gz
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull second set of media updates from Mauro Carvalho Chehab: "Despite its size, most of the stuff here is trivial. This series contains: - s5p-mfc: additions at the driver and at the core to support H.264 hardware codec; - Some improvements at s5p and davinci embedded drivers; - Some V4L2 compliance fixes applied on a few drivers; - Several random trivial patches, including several fixes and a few new board support additions; Notes: 1) Some Exynos media patches were dependent on some -arm fixes that got merged on changeset 782cd9e. That's why this pull request is based that changeset. 2) As promised, I reviewed the pending VB2 DMABUF series. While setting a test environment, it was noticed that the upstream support for Samsung Exynos 4 boards (smdk310 and Origen) are broken upstream, likely due to regressions: both defconfigs are wrong and regulator settings for both boards are broken. That, allied with some bug at the dummy regulator driver, causes OOPSes during boot time. Long story short: even fixing the above, the proposed patches OOPSed when running the DMABUF test. Not sure yet if the OOPSes are due to some other undetected regressions, or due to some bug on the patches. Due to the above, DMABUF patches for vb2 got NACKed for 3.7." * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (109 commits) [media] m5mols: Add missing #include <linux/sizes.h> [media] stk1160: Add support for S-Video input Revert "[media] omap3isp: Replace cpu_is_omap3630() with ISP revision check" [media] dvb: LNA implementation changes [media] v4l2-ioctl: fix W=1 warnings [media] v4l2-ioctl: add blocks check for VIDIOC_SUBDEV_G/S_EDID [media] omap3isp: Fix compilation error in ispreg.h [media] rc-msi-digivox-ii: Add full scan keycodes [media] cx25821: testing the wrong variable [media] tda18271-common: hold the I2C adapter during write transfers [media] ds3000: add module parameter to force firmware upload [media] drivers/media: Remove unnecessary semicolon [media] winbond: remove space from driver name [media] iguanair: cannot send data from the stack [media] omap3isp: Replace cpu_is_omap3630() with ISP revision check [media] dvb-usb: print small buffers via %*ph [media] uvc: Add return code check at vb2_queue_init() [media] em28xx: Replace memcpy with struct assignment [media] bt8xx: Add video4linux control V4L2_CID_COLOR_KILLER [media] mem2mem_testdev: Use devm_kzalloc() in probe ... Conflicts: arch/arm/mach-davinci/include/mach/da8xx.h
Diffstat (limited to 'drivers/media/platform/s5p-fimc/mipi-csis.c')
-rw-r--r--drivers/media/platform/s5p-fimc/mipi-csis.c75
1 files changed, 62 insertions, 13 deletions
diff --git a/drivers/media/platform/s5p-fimc/mipi-csis.c b/drivers/media/platform/s5p-fimc/mipi-csis.c
index e92236a..4c961b1 100644
--- a/drivers/media/platform/s5p-fimc/mipi-csis.c
+++ b/drivers/media/platform/s5p-fimc/mipi-csis.c
@@ -2,7 +2,7 @@
* Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
*
* Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
- * Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -98,6 +98,11 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
#define CSIS_MAX_PIX_WIDTH 0xffff
#define CSIS_MAX_PIX_HEIGHT 0xffff
+/* Non-image packet data buffers */
+#define S5PCSIS_PKTDATA_ODD 0x2000
+#define S5PCSIS_PKTDATA_EVEN 0x3000
+#define S5PCSIS_PKTDATA_SIZE SZ_4K
+
enum {
CSIS_CLK_MUX,
CSIS_CLK_GATE,
@@ -110,8 +115,8 @@ static char *csi_clock_name[] = {
#define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
static const char * const csis_supply_name[] = {
- "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
- "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
+ "vddcore", /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
+ "vddio", /* CSIS I/O and PLL (1.8V) supply */
};
#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
@@ -144,12 +149,18 @@ static const struct s5pcsis_event s5pcsis_events[] = {
};
#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
+struct csis_pktbuf {
+ u32 *data;
+ unsigned int len;
+};
+
/**
* struct csis_state - the driver's internal state data structure
* @lock: mutex serializing the subdev and power management operations,
* protecting @format and @flags members
* @pads: CSIS pads array
* @sd: v4l2_subdev associated with CSIS device instance
+ * @index: the hardware instance index
* @pdev: CSIS platform device
* @regs: mmaped I/O registers memory
* @supplies: CSIS regulator supplies
@@ -159,12 +170,14 @@ static const struct s5pcsis_event s5pcsis_events[] = {
* @csis_fmt: current CSIS pixel format
* @format: common media bus format for the source and sink pad
* @slock: spinlock protecting structure members below
+ * @pkt_buf: the frame embedded (non-image) data buffer
* @events: MIPI-CSIS event (error) counters
*/
struct csis_state {
struct mutex lock;
struct media_pad pads[CSIS_PADS_NUM];
struct v4l2_subdev sd;
+ u8 index;
struct platform_device *pdev;
void __iomem *regs;
struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
@@ -175,6 +188,7 @@ struct csis_state {
struct v4l2_mbus_framefmt format;
struct spinlock slock;
+ struct csis_pktbuf pkt_buf;
struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
};
@@ -202,7 +216,11 @@ static const struct csis_pix_format s5pcsis_formats[] = {
.code = V4L2_MBUS_FMT_JPEG_1X8,
.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
.data_alignment = 32,
- },
+ }, {
+ .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
+ .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
+ .data_alignment = 32,
+ }
};
#define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
@@ -266,7 +284,7 @@ static void __s5pcsis_set_format(struct csis_state *state)
struct v4l2_mbus_framefmt *mf = &state->format;
u32 val;
- v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n",
+ v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
mf->code, mf->width, mf->height);
/* Color format */
@@ -304,8 +322,10 @@ static void s5pcsis_set_params(struct csis_state *state)
val |= S5PCSIS_CTRL_ALIGN_32BIT;
else /* 24-bits */
val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
- /* Not using external clock. */
+
val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
+ if (pdata->wclk_source)
+ val |= S5PCSIS_CTRL_WCLK_EXTCLK;
s5pcsis_write(state, S5PCSIS_CTRL, val);
/* Update the shadow register. */
@@ -529,6 +549,22 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
return 0;
}
+static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf,
+ unsigned int *size)
+{
+ struct csis_state *state = sd_to_csis_state(sd);
+ unsigned long flags;
+
+ *size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE);
+
+ spin_lock_irqsave(&state->slock, flags);
+ state->pkt_buf.data = buf;
+ state->pkt_buf.len = *size;
+ spin_unlock_irqrestore(&state->slock, flags);
+
+ return 0;
+}
+
static int s5pcsis_log_status(struct v4l2_subdev *sd)
{
struct csis_state *state = sd_to_csis_state(sd);
@@ -566,6 +602,7 @@ static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
};
static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
+ .s_rx_buffer = s5pcsis_s_rx_buffer,
.s_stream = s5pcsis_s_stream,
};
@@ -578,13 +615,26 @@ static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
{
struct csis_state *state = dev_id;
+ struct csis_pktbuf *pktbuf = &state->pkt_buf;
unsigned long flags;
u32 status;
status = s5pcsis_read(state, S5PCSIS_INTSRC);
-
spin_lock_irqsave(&state->slock, flags);
+ if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
+ u32 offset;
+
+ if (status & S5PCSIS_INTSRC_EVEN)
+ offset = S5PCSIS_PKTDATA_EVEN;
+ else
+ offset = S5PCSIS_PKTDATA_ODD;
+
+ memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
+ pktbuf->data = NULL;
+ rmb();
+ }
+
/* Update the event/error counters */
if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
int i;
@@ -620,14 +670,15 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
spin_lock_init(&state->slock);
state->pdev = pdev;
+ state->index = max(0, pdev->id);
pdata = pdev->dev.platform_data;
- if (pdata == NULL || pdata->phy_enable == NULL) {
+ if (pdata == NULL) {
dev_err(&pdev->dev, "Platform data not fully specified\n");
return -EINVAL;
}
- if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
+ if ((state->index == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
pdata->lanes > CSIS0_MAX_LANES) {
dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n",
pdata->lanes);
@@ -710,7 +761,6 @@ e_clkput:
static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
{
- struct s5p_platform_mipi_csis *pdata = dev->platform_data;
struct platform_device *pdev = to_platform_device(dev);
struct v4l2_subdev *sd = platform_get_drvdata(pdev);
struct csis_state *state = sd_to_csis_state(sd);
@@ -722,7 +772,7 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
mutex_lock(&state->lock);
if (state->flags & ST_POWERED) {
s5pcsis_stop_stream(state);
- ret = pdata->phy_enable(state->pdev, false);
+ ret = s5p_csis_phy_enable(state->index, false);
if (ret)
goto unlock;
ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
@@ -741,7 +791,6 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
static int s5pcsis_pm_resume(struct device *dev, bool runtime)
{
- struct s5p_platform_mipi_csis *pdata = dev->platform_data;
struct platform_device *pdev = to_platform_device(dev);
struct v4l2_subdev *sd = platform_get_drvdata(pdev);
struct csis_state *state = sd_to_csis_state(sd);
@@ -759,7 +808,7 @@ static int s5pcsis_pm_resume(struct device *dev, bool runtime)
state->supplies);
if (ret)
goto unlock;
- ret = pdata->phy_enable(state->pdev, true);
+ ret = s5p_csis_phy_enable(state->index, true);
if (!ret) {
state->flags |= ST_POWERED;
} else {
OpenPOWER on IntegriCloud