summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c')
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c249
1 files changed, 7 insertions, 242 deletions
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
index e59a219ca480..96a8e11fd55e 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
@@ -6,7 +6,6 @@
*/
#include <linux/of.h>
-#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <media/v4l2-device.h>
@@ -330,55 +329,6 @@ static bool sun6i_csi_capture_format_match(u32 pixelformat, u32 mbus_code)
/* Capture */
-static void sun6i_csi_capture_irq_enable(struct sun6i_csi_device *csi_dev)
-{
- struct regmap *regmap = csi_dev->regmap;
-
- regmap_write(regmap, SUN6I_CSI_CH_INT_EN_REG,
- SUN6I_CSI_CH_INT_EN_VS |
- SUN6I_CSI_CH_INT_EN_HB_OF |
- SUN6I_CSI_CH_INT_EN_FIFO2_OF |
- SUN6I_CSI_CH_INT_EN_FIFO1_OF |
- SUN6I_CSI_CH_INT_EN_FIFO0_OF |
- SUN6I_CSI_CH_INT_EN_FD |
- SUN6I_CSI_CH_INT_EN_CD);
-}
-
-static void sun6i_csi_capture_irq_disable(struct sun6i_csi_device *csi_dev)
-{
- struct regmap *regmap = csi_dev->regmap;
-
- regmap_write(regmap, SUN6I_CSI_CH_INT_EN_REG, 0);
-}
-
-static void sun6i_csi_capture_irq_clear(struct sun6i_csi_device *csi_dev)
-{
- struct regmap *regmap = csi_dev->regmap;
-
- regmap_write(regmap, SUN6I_CSI_CH_INT_EN_REG, 0);
- regmap_write(regmap, SUN6I_CSI_CH_INT_STA_REG,
- SUN6I_CSI_CH_INT_STA_CLEAR);
-}
-
-static void sun6i_csi_capture_enable(struct sun6i_csi_device *csi_dev)
-{
- struct regmap *regmap = csi_dev->regmap;
-
- regmap_update_bits(regmap, SUN6I_CSI_EN_REG, SUN6I_CSI_EN_CSI_EN,
- SUN6I_CSI_EN_CSI_EN);
-
- regmap_update_bits(regmap, SUN6I_CSI_CAP_REG, SUN6I_CSI_CAP_VCAP_ON,
- SUN6I_CSI_CAP_VCAP_ON);
-}
-
-static void sun6i_csi_capture_disable(struct sun6i_csi_device *csi_dev)
-{
- struct regmap *regmap = csi_dev->regmap;
-
- regmap_update_bits(regmap, SUN6I_CSI_CAP_REG, SUN6I_CSI_CAP_VCAP_ON, 0);
- regmap_update_bits(regmap, SUN6I_CSI_EN_REG, SUN6I_CSI_EN_CSI_EN, 0);
-}
-
static void
sun6i_csi_capture_buffer_configure(struct sun6i_csi_device *csi_dev,
struct sun6i_csi_buffer *csi_buffer)
@@ -420,148 +370,7 @@ sun6i_csi_capture_buffer_configure(struct sun6i_csi_device *csi_dev,
}
}
-static void
-sun6i_csi_capture_configure_interface(struct sun6i_csi_device *csi_dev)
-{
- struct device *dev = csi_dev->dev;
- struct regmap *regmap = csi_dev->regmap;
- struct v4l2_fwnode_endpoint *endpoint =
- &csi_dev->bridge.source_parallel.endpoint;
- unsigned char bus_width = endpoint->bus.parallel.bus_width;
- unsigned int flags = endpoint->bus.parallel.flags;
- u32 pixelformat, field;
- u32 value = SUN6I_CSI_IF_CFG_IF_CSI;
-
- sun6i_csi_capture_format(csi_dev, &pixelformat, &field);
-
- if (field == V4L2_FIELD_INTERLACED ||
- field == V4L2_FIELD_INTERLACED_TB ||
- field == V4L2_FIELD_INTERLACED_BT)
- value |= SUN6I_CSI_IF_CFG_SRC_TYPE_INTERLACED |
- SUN6I_CSI_IF_CFG_FIELD_DT_PCLK_SHIFT(1) |
- SUN6I_CSI_IF_CFG_FIELD_DT_FIELD_VSYNC;
- else
- value |= SUN6I_CSI_IF_CFG_SRC_TYPE_PROGRESSIVE;
-
- switch (endpoint->bus_type) {
- case V4L2_MBUS_PARALLEL:
- if (bus_width == 16)
- value |= SUN6I_CSI_IF_CFG_IF_CSI_YUV_COMBINED;
- else
- value |= SUN6I_CSI_IF_CFG_IF_CSI_YUV_RAW;
-
- if (flags & V4L2_MBUS_FIELD_EVEN_LOW)
- value |= SUN6I_CSI_IF_CFG_FIELD_NEGATIVE;
- else
- value |= SUN6I_CSI_IF_CFG_FIELD_POSITIVE;
-
- if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
- value |= SUN6I_CSI_IF_CFG_VREF_POL_NEGATIVE;
- else
- value |= SUN6I_CSI_IF_CFG_VREF_POL_POSITIVE;
-
- if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
- value |= SUN6I_CSI_IF_CFG_HREF_POL_NEGATIVE;
- else
- value |= SUN6I_CSI_IF_CFG_HREF_POL_POSITIVE;
-
- if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
- value |= SUN6I_CSI_IF_CFG_CLK_POL_RISING;
- else
- value |= SUN6I_CSI_IF_CFG_CLK_POL_FALLING;
- break;
- case V4L2_MBUS_BT656:
- if (bus_width == 16)
- value |= SUN6I_CSI_IF_CFG_IF_CSI_BT1120;
- else
- value |= SUN6I_CSI_IF_CFG_IF_CSI_BT656;
-
- if (flags & V4L2_MBUS_FIELD_EVEN_LOW)
- value |= SUN6I_CSI_IF_CFG_FIELD_NEGATIVE;
- else
- value |= SUN6I_CSI_IF_CFG_FIELD_POSITIVE;
-
- if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
- value |= SUN6I_CSI_IF_CFG_CLK_POL_RISING;
- else
- value |= SUN6I_CSI_IF_CFG_CLK_POL_FALLING;
- break;
- default:
- dev_warn(dev, "unsupported bus type: %d\n", endpoint->bus_type);
- break;
- }
-
- switch (bus_width) {
- case 8:
- /* 16-bit YUV formats use a doubled width in 8-bit mode. */
- case 16:
- value |= SUN6I_CSI_IF_CFG_DATA_WIDTH_8;
- break;
- case 10:
- value |= SUN6I_CSI_IF_CFG_DATA_WIDTH_10;
- break;
- case 12:
- value |= SUN6I_CSI_IF_CFG_DATA_WIDTH_12;
- break;
- default:
- dev_warn(dev, "unsupported bus width: %u\n", bus_width);
- break;
- }
-
- regmap_write(regmap, SUN6I_CSI_IF_CFG_REG, value);
-}
-
-static void sun6i_csi_capture_configure_format(struct sun6i_csi_device *csi_dev)
-{
- struct regmap *regmap = csi_dev->regmap;
- const struct sun6i_csi_bridge_format *bridge_format;
- const struct sun6i_csi_capture_format *capture_format;
- u32 mbus_code, pixelformat, field;
- u8 input_format, input_yuv_seq, output_format;
- u32 value = 0;
-
- sun6i_csi_capture_format(csi_dev, &pixelformat, &field);
- sun6i_csi_bridge_format(csi_dev, &mbus_code, NULL);
-
- bridge_format = sun6i_csi_bridge_format_find(mbus_code);
- if (WARN_ON(!bridge_format))
- return;
-
- input_format = bridge_format->input_format;
- input_yuv_seq = bridge_format->input_yuv_seq;
-
- capture_format = sun6i_csi_capture_format_find(pixelformat);
- if (WARN_ON(!capture_format))
- return;
-
- if (capture_format->input_format_raw)
- input_format = SUN6I_CSI_INPUT_FMT_RAW;
-
- if (capture_format->input_yuv_seq_invert)
- input_yuv_seq = bridge_format->input_yuv_seq_invert;
-
- if (field == V4L2_FIELD_INTERLACED ||
- field == V4L2_FIELD_INTERLACED_TB ||
- field == V4L2_FIELD_INTERLACED_BT)
- output_format = capture_format->output_format_field;
- else
- output_format = capture_format->output_format_frame;
-
- value |= SUN6I_CSI_CH_CFG_OUTPUT_FMT(output_format);
- value |= SUN6I_CSI_CH_CFG_INPUT_FMT(input_format);
- value |= SUN6I_CSI_CH_CFG_INPUT_YUV_SEQ(input_yuv_seq);
-
- if (field == V4L2_FIELD_TOP)
- value |= SUN6I_CSI_CH_CFG_FIELD_SEL_FIELD0;
- else if (field == V4L2_FIELD_BOTTOM)
- value |= SUN6I_CSI_CH_CFG_FIELD_SEL_FIELD1;
- else
- value |= SUN6I_CSI_CH_CFG_FIELD_SEL_EITHER;
-
- regmap_write(regmap, SUN6I_CSI_CH_CFG_REG, value);
-}
-
-static void sun6i_csi_capture_configure_window(struct sun6i_csi_device *csi_dev)
+void sun6i_csi_capture_configure(struct sun6i_csi_device *csi_dev)
{
struct regmap *regmap = csi_dev->regmap;
const struct sun6i_csi_capture_format *format;
@@ -624,13 +433,6 @@ static void sun6i_csi_capture_configure_window(struct sun6i_csi_device *csi_dev)
SUN6I_CSI_CH_BUF_LEN_LUMA_LINE(luma_line));
}
-static void sun6i_csi_capture_configure(struct sun6i_csi_device *csi_dev)
-{
- sun6i_csi_capture_configure_interface(csi_dev);
- sun6i_csi_capture_configure_format(csi_dev);
- sun6i_csi_capture_configure_window(csi_dev);
-}
-
/* State */
static void sun6i_csi_capture_state_cleanup(struct sun6i_csi_device *csi_dev,
@@ -670,7 +472,7 @@ static void sun6i_csi_capture_state_cleanup(struct sun6i_csi_device *csi_dev,
spin_unlock_irqrestore(&state->lock, flags);
}
-static void sun6i_csi_capture_state_update(struct sun6i_csi_device *csi_dev)
+void sun6i_csi_capture_state_update(struct sun6i_csi_device *csi_dev)
{
struct sun6i_csi_capture_state *state = &csi_dev->capture.state;
struct sun6i_csi_buffer *csi_buffer;
@@ -803,11 +605,9 @@ static int sun6i_csi_capture_start_streaming(struct vb2_queue *queue,
unsigned int count)
{
struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue);
- struct sun6i_csi_capture *capture = &csi_dev->capture;
- struct sun6i_csi_capture_state *state = &capture->state;
- struct video_device *video_dev = &capture->video_dev;
+ struct sun6i_csi_capture_state *state = &csi_dev->capture.state;
+ struct video_device *video_dev = &csi_dev->capture.video_dev;
struct v4l2_subdev *subdev = &csi_dev->bridge.subdev;
- struct device *dev = csi_dev->dev;
int ret;
state->sequence = 0;
@@ -816,41 +616,12 @@ static int sun6i_csi_capture_start_streaming(struct vb2_queue *queue,
if (ret < 0)
goto error_state;
- /* PM */
-
- ret = pm_runtime_resume_and_get(dev);
- if (ret < 0)
- goto error_media_pipeline;
-
- /* Clear */
-
- sun6i_csi_capture_irq_clear(csi_dev);
-
- /* Configure */
-
- sun6i_csi_capture_configure(csi_dev);
-
- /* State Update */
-
- sun6i_csi_capture_state_update(csi_dev);
-
- /* Enable */
-
- sun6i_csi_capture_irq_enable(csi_dev);
- sun6i_csi_capture_enable(csi_dev);
-
ret = v4l2_subdev_call(subdev, video, s_stream, 1);
if (ret && ret != -ENOIOCTLCMD)
- goto error_stream;
+ goto error_media_pipeline;
return 0;
-error_stream:
- sun6i_csi_capture_disable(csi_dev);
- sun6i_csi_capture_irq_disable(csi_dev);
-
- pm_runtime_put(dev);
-
error_media_pipeline:
video_device_pipeline_stop(video_dev);
@@ -863,18 +634,12 @@ error_state:
static void sun6i_csi_capture_stop_streaming(struct vb2_queue *queue)
{
struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue);
- struct sun6i_csi_capture *capture = &csi_dev->capture;
+ struct video_device *video_dev = &csi_dev->capture.video_dev;
struct v4l2_subdev *subdev = &csi_dev->bridge.subdev;
- struct device *dev = csi_dev->dev;
v4l2_subdev_call(subdev, video, s_stream, 0);
- sun6i_csi_capture_disable(csi_dev);
- sun6i_csi_capture_irq_disable(csi_dev);
-
- pm_runtime_put(dev);
-
- video_device_pipeline_stop(&capture->video_dev);
+ video_device_pipeline_stop(video_dev);
sun6i_csi_capture_state_cleanup(csi_dev, true);
}