camif-core.c revision 250539a36f69aa51e4c68a1f92c4ed2bcc042a1a
1babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki/*
2babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * s3c24xx/s3c64xx SoC series Camera Interface (CAMIF) driver
3babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki *
4babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
5babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * Copyright (C) 2012 Tomasz Figa <tomasz.figa@gmail.com>
6babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki *
7babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * This program is free software; you can redistribute it and/or modify
8babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * it under the terms of the GNU General Public License as published
9babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * by the Free Software Foundation, either version 2 of the License,
10babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * or (at your option) any later version.
11babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki */
12babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
13babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
14babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/bug.h>
15babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/clk.h>
16babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/delay.h>
17babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/device.h>
18babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/errno.h>
19babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/gpio.h>
20babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/i2c.h>
21babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/interrupt.h>
22babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/io.h>
23babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/kernel.h>
24babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/list.h>
25babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/module.h>
26babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/platform_device.h>
27babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/pm_runtime.h>
28babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/slab.h>
29babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <linux/types.h>
30250539a36f69aa51e4c68a1f92c4ed2bcc042a1aSachin Kamat#include <linux/version.h>
31babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
32babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <media/media-device.h>
33babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <media/v4l2-ctrls.h>
34babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <media/v4l2-ioctl.h>
35babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <media/videobuf2-core.h>
36babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include <media/videobuf2-dma-contig.h>
37babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
38babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki#include "camif-core.h"
39babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
40babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic char *camif_clocks[CLK_MAX_NUM] = {
41babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	/* HCLK CAMIF clock */
42babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	[CLK_GATE]	= "camif",
43babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	/* CAMIF / external camera sensor master clock */
44babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	[CLK_CAM]	= "camera",
45babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki};
46babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
47babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic const struct camif_fmt camif_formats[] = {
48babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	{
49babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.name		= "YUV 4:2:2 planar, Y/Cb/Cr",
50babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.fourcc		= V4L2_PIX_FMT_YUV422P,
51babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.depth		= 16,
52babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.ybpp		= 1,
53babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.color		= IMG_FMT_YCBCR422P,
54babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.colplanes	= 3,
55babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.flags		= FMT_FL_S3C24XX_CODEC |
56babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				  FMT_FL_S3C64XX,
57babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}, {
58babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.name		= "YUV 4:2:0 planar, Y/Cb/Cr",
59babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.fourcc		= V4L2_PIX_FMT_YUV420,
60babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.depth		= 12,
61babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.ybpp		= 1,
62babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.color		= IMG_FMT_YCBCR420,
63babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.colplanes	= 3,
64babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.flags		= FMT_FL_S3C24XX_CODEC |
65babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				  FMT_FL_S3C64XX,
66babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}, {
67babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.name		= "YVU 4:2:0 planar, Y/Cr/Cb",
68babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.fourcc		= V4L2_PIX_FMT_YVU420,
69babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.depth		= 12,
70babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.ybpp		= 1,
71babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.color		= IMG_FMT_YCRCB420,
72babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.colplanes	= 3,
73babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.flags		= FMT_FL_S3C24XX_CODEC |
74babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				  FMT_FL_S3C64XX,
75babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}, {
76babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.name		= "RGB565, 16 bpp",
77babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.fourcc		= V4L2_PIX_FMT_RGB565X,
78babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.depth		= 16,
79babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.ybpp		= 2,
80babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.color		= IMG_FMT_RGB565,
81babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.colplanes	= 1,
82babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.flags		= FMT_FL_S3C24XX_PREVIEW |
83babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				  FMT_FL_S3C64XX,
84babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}, {
85babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.name		= "XRGB8888, 32 bpp",
86babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.fourcc		= V4L2_PIX_FMT_RGB32,
87babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.depth		= 32,
88babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.ybpp		= 4,
89babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.color		= IMG_FMT_XRGB8888,
90babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.colplanes	= 1,
91babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.flags		= FMT_FL_S3C24XX_PREVIEW |
92babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				  FMT_FL_S3C64XX,
93babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}, {
94babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.name		= "BGR666",
95babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.fourcc		= V4L2_PIX_FMT_BGR666,
96babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.depth		= 32,
97babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.ybpp		= 4,
98babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.color		= IMG_FMT_RGB666,
99babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.colplanes	= 1,
100babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.flags		= FMT_FL_S3C64XX,
101babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
102babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki};
103babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
104babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki/**
105babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * s3c_camif_find_format() - lookup camif color format by fourcc or an index
106babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * @pixelformat: fourcc to match, ignored if null
107babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * @index: index to the camif_formats array, ignored if negative
108babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki */
109babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockiconst struct camif_fmt *s3c_camif_find_format(struct camif_vp *vp,
110babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki					      const u32 *pixelformat,
111babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki					      int index)
112babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
113babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	const struct camif_fmt *fmt, *def_fmt = NULL;
114babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	unsigned int i;
115babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int id = 0;
116babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
117babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (index >= (int)ARRAY_SIZE(camif_formats))
118babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return NULL;
119babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
120babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	for (i = 0; i < ARRAY_SIZE(camif_formats); ++i) {
121babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		fmt = &camif_formats[i];
122babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		if (vp && !(vp->fmt_flags & fmt->flags))
123babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			continue;
124babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		if (pixelformat && fmt->fourcc == *pixelformat)
125babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			return fmt;
126babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		if (index == id)
127babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			def_fmt = fmt;
128babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		id++;
129babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
130babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return def_fmt;
131babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
132babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
133babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int camif_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
134babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
135babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	unsigned int sh = 6;
136babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
137babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (src >= 64 * tar)
138babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return -EINVAL;
139babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
140babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	while (sh--) {
141babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		unsigned int tmp = 1 << sh;
142babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		if (src >= tar * tmp) {
143babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			*shift = sh, *ratio = tmp;
144babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			return 0;
145babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		}
146babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
147babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	*shift = 0, *ratio = 1;
148babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return 0;
149babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
150babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
151babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockiint s3c_camif_get_scaler_config(struct camif_vp *vp,
152babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				struct camif_scaler *scaler)
153babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
154babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct v4l2_rect *camif_crop = &vp->camif->camif_crop;
155babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int source_x = camif_crop->width;
156babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int source_y = camif_crop->height;
157babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int target_x = vp->out_frame.rect.width;
158babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int target_y = vp->out_frame.rect.height;
159babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int ret;
160babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
161babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (vp->rotation == 90 || vp->rotation == 270)
162babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		swap(target_x, target_y);
163babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
164babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = camif_get_scaler_factor(source_x, target_x, &scaler->pre_h_ratio,
165babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				      &scaler->h_shift);
166babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
167babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return ret;
168babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
169babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = camif_get_scaler_factor(source_y, target_y, &scaler->pre_v_ratio,
170babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				      &scaler->v_shift);
171babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
172babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return ret;
173babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
174babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	scaler->pre_dst_width = source_x / scaler->pre_h_ratio;
175babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	scaler->pre_dst_height = source_y / scaler->pre_v_ratio;
176babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
177babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	scaler->main_h_ratio = (source_x << 8) / (target_x << scaler->h_shift);
178babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	scaler->main_v_ratio = (source_y << 8) / (target_y << scaler->v_shift);
179babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
180babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	scaler->scaleup_h = (target_x >= source_x);
181babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	scaler->scaleup_v = (target_y >= source_y);
182babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
183babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	scaler->copy = 0;
184babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
185babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	pr_debug("H: ratio: %u, shift: %u. V: ratio: %u, shift: %u.\n",
186babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		 scaler->pre_h_ratio, scaler->h_shift,
187babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		 scaler->pre_v_ratio, scaler->v_shift);
188babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
189babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	pr_debug("Source: %dx%d, Target: %dx%d, scaleup_h/v: %d/%d\n",
190babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		 source_x, source_y, target_x, target_y,
191babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		 scaler->scaleup_h, scaler->scaleup_v);
192babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
193babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return 0;
194babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
195babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
196babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int camif_register_sensor(struct camif_dev *camif)
197babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
198babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct s3c_camif_sensor_info *sensor = &camif->pdata.sensor;
199babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct v4l2_device *v4l2_dev = &camif->v4l2_dev;
200babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct i2c_adapter *adapter;
201babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct v4l2_subdev_format format;
202babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct v4l2_subdev *sd;
203babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int ret;
204babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
205babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif->sensor.sd = NULL;
206babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
207babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (sensor->i2c_board_info.addr == 0)
208babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return -EINVAL;
209babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
210babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	adapter = i2c_get_adapter(sensor->i2c_bus_num);
211babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (adapter == NULL) {
212babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		v4l2_warn(v4l2_dev, "failed to get I2C adapter %d\n",
213babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			  sensor->i2c_bus_num);
214babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return -EPROBE_DEFER;
215babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
216babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
217babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter,
218babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				       &sensor->i2c_board_info, NULL);
219babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (sd == NULL) {
220babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		i2c_put_adapter(adapter);
221babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		v4l2_warn(v4l2_dev, "failed to acquire subdev %s\n",
222babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			  sensor->i2c_board_info.type);
223babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return -EPROBE_DEFER;
224babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
225babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif->sensor.sd = sd;
226babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
227babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	v4l2_info(v4l2_dev, "registered sensor subdevice %s\n", sd->name);
228babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
229babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	/* Get initial pixel format and set it at the camif sink pad */
230babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	format.pad = 0;
231babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
232babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &format);
233babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
234babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
235babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return 0;
236babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
237babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	format.pad = CAMIF_SD_PAD_SINK;
238babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	v4l2_subdev_call(&camif->subdev, pad, set_fmt, NULL, &format);
239babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
240babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	v4l2_info(sd, "Initial format from sensor: %dx%d, %#x\n",
241babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		  format.format.width, format.format.height,
242babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		  format.format.code);
243babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return 0;
244babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
245babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
246babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic void camif_unregister_sensor(struct camif_dev *camif)
247babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
248babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct v4l2_subdev *sd = camif->sensor.sd;
249babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct i2c_client *client = sd ? v4l2_get_subdevdata(sd) : NULL;
250babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct i2c_adapter *adapter;
251babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
252babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (client == NULL)
253babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return;
254babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
255babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	adapter = client->adapter;
256babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	v4l2_device_unregister_subdev(sd);
257babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif->sensor.sd = NULL;
258babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	i2c_unregister_device(client);
259babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (adapter)
260babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		i2c_put_adapter(adapter);
261babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
262babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
263babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int camif_create_media_links(struct camif_dev *camif)
264babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
265babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int i, ret;
266babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
267babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = media_entity_create_link(&camif->sensor.sd->entity, 0,
268babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				&camif->subdev.entity, CAMIF_SD_PAD_SINK,
269babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				MEDIA_LNK_FL_IMMUTABLE |
270babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				MEDIA_LNK_FL_ENABLED);
271babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret)
272babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return ret;
273babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
274babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	for (i = 1; i < CAMIF_SD_PADS_NUM && !ret; i++) {
275babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		ret = media_entity_create_link(&camif->subdev.entity, i,
276babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				&camif->vp[i - 1].vdev.entity, 0,
277babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				MEDIA_LNK_FL_IMMUTABLE |
278babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				MEDIA_LNK_FL_ENABLED);
279babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
280babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
281babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return ret;
282babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
283babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
284babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int camif_register_video_nodes(struct camif_dev *camif)
285babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
286babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int ret = s3c_camif_register_video_node(camif, VP_CODEC);
287babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
288babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return ret;
289babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
290babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return s3c_camif_register_video_node(camif, VP_PREVIEW);
291babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
292babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
293babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic void camif_unregister_video_nodes(struct camif_dev *camif)
294babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
295babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	s3c_camif_unregister_video_node(camif, VP_CODEC);
296babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	s3c_camif_unregister_video_node(camif, VP_PREVIEW);
297babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
298babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
299babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic void camif_unregister_media_entities(struct camif_dev *camif)
300babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
301babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif_unregister_video_nodes(camif);
302babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif_unregister_sensor(camif);
303babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	s3c_camif_unregister_subdev(camif);
304babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
305babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
306babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki/*
307babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * Media device
308babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki */
309babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int camif_media_dev_register(struct camif_dev *camif)
310babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
311babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct media_device *md = &camif->media_dev;
312babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct v4l2_device *v4l2_dev = &camif->v4l2_dev;
313babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	unsigned int ip_rev = camif->variant->ip_revision;
314babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int ret;
315babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
316babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	memset(md, 0, sizeof(*md));
317babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	snprintf(md->model, sizeof(md->model), "SAMSUNG S3C%s CAMIF",
318babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		 ip_rev == S3C6410_CAMIF_IP_REV ? "6410" : "244X");
319babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	strlcpy(md->bus_info, "platform", sizeof(md->bus_info));
320babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	md->hw_revision = ip_rev;
321babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	md->driver_version = KERNEL_VERSION(1, 0, 0);
322babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
323babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	md->dev = camif->dev;
324babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
325babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	strlcpy(v4l2_dev->name, "s3c-camif", sizeof(v4l2_dev->name));
326babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	v4l2_dev->mdev = md;
327babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
328babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = v4l2_device_register(camif->dev, v4l2_dev);
329babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
330babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return ret;
331babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
332babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = media_device_register(md);
333babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
334babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		v4l2_device_unregister(v4l2_dev);
335babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
336babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return ret;
337babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
338babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
339babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic void camif_clk_put(struct camif_dev *camif)
340babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
341babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int i;
342babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
343babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	for (i = 0; i < CLK_MAX_NUM; i++) {
344babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		if (IS_ERR_OR_NULL(camif->clock[i]))
345babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			continue;
346babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		clk_unprepare(camif->clock[i]);
347babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		clk_put(camif->clock[i]);
348babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
349babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
350babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
351babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int camif_clk_get(struct camif_dev *camif)
352babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
353babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int ret, i;
354babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
355babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	for (i = 0; i < CLK_MAX_NUM; i++) {
356babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		camif->clock[i] = clk_get(camif->dev, camif_clocks[i]);
357babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		if (IS_ERR(camif->clock[i])) {
358babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			ret = PTR_ERR(camif->clock[i]);
359babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			goto err;
360babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		}
361babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		ret = clk_prepare(camif->clock[i]);
362babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		if (ret < 0) {
363babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			clk_put(camif->clock[i]);
364babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			camif->clock[i] = NULL;
365babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			goto err;
366babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		}
367babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
368babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return 0;
369babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockierr:
370babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif_clk_put(camif);
371babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	dev_err(camif->dev, "failed to get clock: %s\n",
372babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		camif_clocks[i]);
373babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return ret;
374babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
375babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
376babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki/*
377babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * The CAMIF device has two relatively independent data processing paths
378babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * that can source data from memory or the common camera input frontend.
379babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki * Register interrupts for each data processing path (camif_vp).
380babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki */
381babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int camif_request_irqs(struct platform_device *pdev,
382babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			      struct camif_dev *camif)
383babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
384babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int irq, ret, i;
385babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
386babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	for (i = 0; i < CAMIF_VP_NUM; i++) {
387babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		struct camif_vp *vp = &camif->vp[i];
388babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
389babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		init_waitqueue_head(&vp->irq_queue);
390babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
391babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		irq = platform_get_irq(pdev, i);
392babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		if (irq <= 0) {
393babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			dev_err(&pdev->dev, "failed to get IRQ %d\n", i);
394babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			return -ENXIO;
395babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		}
396babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
397babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		ret = devm_request_irq(&pdev->dev, irq, s3c_camif_irq_handler,
398babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki				       0, dev_name(&pdev->dev), vp);
399babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		if (ret < 0) {
400babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			dev_err(&pdev->dev, "failed to install IRQ: %d\n", ret);
401babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			break;
402babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		}
403babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
404babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
405babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return ret;
406babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
407babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
408babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int s3c_camif_probe(struct platform_device *pdev)
409babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
410babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct device *dev = &pdev->dev;
411babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct s3c_camif_plat_data *pdata = dev->platform_data;
412babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct s3c_camif_drvdata *drvdata;
413babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct camif_dev *camif;
414babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct resource *mres;
415babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	int ret = 0;
416babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
417babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif = devm_kzalloc(dev, sizeof(*camif), GFP_KERNEL);
418babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (!camif)
419babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return -ENOMEM;
420babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
421babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	spin_lock_init(&camif->slock);
422babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	mutex_init(&camif->lock);
423babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
424babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif->dev = dev;
425babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
426babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (!pdata || !pdata->gpio_get || !pdata->gpio_put) {
427babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		dev_err(dev, "wrong platform data\n");
428babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return -EINVAL;
429babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
430babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
431babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif->pdata = *pdata;
432babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	drvdata = (void *)platform_get_device_id(pdev)->driver_data;
433babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif->variant = drvdata->variant;
434babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
435babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
436babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
437babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif->io_base = devm_request_and_ioremap(dev, mres);
438babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (!camif->io_base) {
439babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		dev_err(dev, "failed to obtain I/O memory\n");
440babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return -ENOENT;
441babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
442babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
443babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = camif_request_irqs(pdev, camif);
444babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
445babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return ret;
446babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
447babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = pdata->gpio_get();
448babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
449babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		return ret;
450babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
451babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = s3c_camif_create_subdev(camif);
452babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
453babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		goto err_sd;
454babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
455babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = camif_clk_get(camif);
456babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
457babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		goto err_clk;
458babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
459babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	platform_set_drvdata(pdev, camif);
460babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	clk_set_rate(camif->clock[CLK_CAM],
461babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			camif->pdata.sensor.clock_frequency);
462babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
463babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	dev_info(dev, "sensor clock frequency: %lu\n",
464babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		 clk_get_rate(camif->clock[CLK_CAM]));
465babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	/*
466babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	 * Set initial pixel format, resolution and crop rectangle.
467babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	 * Must be done before a sensor subdev is registered as some
468babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	 * settings are overrode with values from sensor subdev.
469babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	 */
470babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	s3c_camif_set_defaults(camif);
471babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
472babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	pm_runtime_enable(dev);
473babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
474babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = pm_runtime_get_sync(dev);
475babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
476babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		goto err_pm;
477babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
478babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	/* Initialize contiguous memory allocator */
479babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif->alloc_ctx = vb2_dma_contig_init_ctx(dev);
480babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (IS_ERR(camif->alloc_ctx)) {
481babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		ret = PTR_ERR(camif->alloc_ctx);
482babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		goto err_alloc;
483babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
484babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
485babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = camif_media_dev_register(camif);
486babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
487babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		goto err_mdev;
488babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
489babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = camif_register_sensor(camif);
490babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
491babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		goto err_sens;
492babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
493babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = v4l2_device_register_subdev(&camif->v4l2_dev, &camif->subdev);
494babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
495babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		goto err_sens;
496babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
497babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	mutex_lock(&camif->media_dev.graph_mutex);
498babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
499babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = v4l2_device_register_subdev_nodes(&camif->v4l2_dev);
500babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
501babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		goto err_unlock;
502babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
503babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = camif_register_video_nodes(camif);
504babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
505babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		goto err_unlock;
506babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
507babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	ret = camif_create_media_links(camif);
508babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	if (ret < 0)
509babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		goto err_unlock;
510babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
511babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	mutex_unlock(&camif->media_dev.graph_mutex);
512babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	pm_runtime_put(dev);
513babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return 0;
514babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
515babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockierr_unlock:
516babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	mutex_unlock(&camif->media_dev.graph_mutex);
517babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockierr_sens:
518babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	v4l2_device_unregister(&camif->v4l2_dev);
519babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	media_device_unregister(&camif->media_dev);
520babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif_unregister_media_entities(camif);
521babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockierr_mdev:
522babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	vb2_dma_contig_cleanup_ctx(camif->alloc_ctx);
523babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockierr_alloc:
524babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	pm_runtime_put(dev);
525babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	pm_runtime_disable(dev);
526babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockierr_pm:
527babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif_clk_put(camif);
528babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockierr_clk:
529babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	s3c_camif_unregister_subdev(camif);
530babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockierr_sd:
531babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	pdata->gpio_put();
532babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return ret;
533babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
534babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
535babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int __devexit s3c_camif_remove(struct platform_device *pdev)
536babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
537babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct camif_dev *camif = platform_get_drvdata(pdev);
538babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct s3c_camif_plat_data *pdata = &camif->pdata;
539babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
540babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	media_device_unregister(&camif->media_dev);
541babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif_unregister_media_entities(camif);
542babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	v4l2_device_unregister(&camif->v4l2_dev);
543babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
544babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	pm_runtime_disable(&pdev->dev);
545babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	camif_clk_put(camif);
546babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	pdata->gpio_put();
547babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
548babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return 0;
549babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
550babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
551babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int s3c_camif_runtime_resume(struct device *dev)
552babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
553babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct camif_dev *camif = dev_get_drvdata(dev);
554babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
555babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	clk_enable(camif->clock[CLK_GATE]);
556babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	/* null op on s3c244x */
557babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	clk_enable(camif->clock[CLK_CAM]);
558babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return 0;
559babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
560babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
561babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic int s3c_camif_runtime_suspend(struct device *dev)
562babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki{
563babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	struct camif_dev *camif = dev_get_drvdata(dev);
564babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
565babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	/* null op on s3c244x */
566babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	clk_disable(camif->clock[CLK_CAM]);
567babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
568babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	clk_disable(camif->clock[CLK_GATE]);
569babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	return 0;
570babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki}
571babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
572babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic const struct s3c_camif_variant s3c244x_camif_variant = {
573babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.vp_pix_limits = {
574babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		[VP_CODEC] = {
575babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_out_width		= 4096,
576babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_sc_out_width	= 2048,
577babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.out_width_align	= 16,
578babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.min_out_width		= 16,
579babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_height		= 4096,
580babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		},
581babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		[VP_PREVIEW] = {
582babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_out_width		= 640,
583babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_sc_out_width	= 640,
584babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.out_width_align	= 16,
585babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.min_out_width		= 16,
586babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_height		= 480,
587babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		}
588babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	},
589babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.pix_limits = {
590babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.win_hor_offset_align	= 8,
591babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	},
592babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.ip_revision = S3C244X_CAMIF_IP_REV,
593babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki};
594babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
595babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic struct s3c_camif_drvdata s3c244x_camif_drvdata = {
596babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.variant	= &s3c244x_camif_variant,
597babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.bus_clk_freq	= 24000000UL,
598babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki};
599babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
600babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic const struct s3c_camif_variant s3c6410_camif_variant = {
601babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.vp_pix_limits = {
602babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		[VP_CODEC] = {
603babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_out_width		= 4096,
604babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_sc_out_width	= 2048,
605babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.out_width_align	= 16,
606babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.min_out_width		= 16,
607babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_height		= 4096,
608babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		},
609babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		[VP_PREVIEW] = {
610babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_out_width		= 4096,
611babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_sc_out_width	= 720,
612babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.out_width_align	= 16,
613babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.min_out_width		= 16,
614babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki			.max_height		= 4096,
615babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		}
616babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	},
617babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.pix_limits = {
618babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.win_hor_offset_align	= 8,
619babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	},
620babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.ip_revision = S3C6410_CAMIF_IP_REV,
621babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.has_img_effect = 1,
622babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.vp_offset = 0x20,
623babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki};
624babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
625babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic struct s3c_camif_drvdata s3c6410_camif_drvdata = {
626babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.variant	= &s3c6410_camif_variant,
627babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.bus_clk_freq	= 133000000UL,
628babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki};
629babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
630babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic struct platform_device_id s3c_camif_driver_ids[] = {
631babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	{
632babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.name		= "s3c2440-camif",
633babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.driver_data	= (unsigned long)&s3c244x_camif_drvdata,
634babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}, {
635babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.name		= "s3c6410-camif",
636babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.driver_data	= (unsigned long)&s3c6410_camif_drvdata,
637babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	},
638babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	{ /* sentinel */ },
639babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki};
640babde1c243b25592038dd7193867a49729e3d505Sylwester NawrockiMODULE_DEVICE_TABLE(platform, s3c_camif_driver_ids);
641babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
642babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic const struct dev_pm_ops s3c_camif_pm_ops = {
643babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.runtime_suspend	= s3c_camif_runtime_suspend,
644babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.runtime_resume		= s3c_camif_runtime_resume,
645babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki};
646babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
647babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockistatic struct platform_driver s3c_camif_driver = {
648babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.probe		= s3c_camif_probe,
649babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.remove		= __devexit_p(s3c_camif_remove),
650babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.id_table	= s3c_camif_driver_ids,
651babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	.driver = {
652babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.name	= S3C_CAMIF_DRIVER_NAME,
653babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.owner	= THIS_MODULE,
654babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki		.pm	= &s3c_camif_pm_ops,
655babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki	}
656babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki};
657babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
658babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrockimodule_platform_driver(s3c_camif_driver);
659babde1c243b25592038dd7193867a49729e3d505Sylwester Nawrocki
660babde1c243b25592038dd7193867a49729e3d505Sylwester NawrockiMODULE_AUTHOR("Sylwester Nawrocki <sylvester.nawrocki@gmail.com>");
661babde1c243b25592038dd7193867a49729e3d505Sylwester NawrockiMODULE_AUTHOR("Tomasz Figa <tomasz.figa@gmail.com>");
662babde1c243b25592038dd7193867a49729e3d505Sylwester NawrockiMODULE_DESCRIPTION("S3C24XX/S3C64XX SoC camera interface driver");
663babde1c243b25592038dd7193867a49729e3d505Sylwester NawrockiMODULE_LICENSE("GPL");
664