aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tegra
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/video/tegra
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/media/video/tegra')
-rw-r--r--drivers/media/video/tegra/Kconfig90
-rw-r--r--drivers/media/video/tegra/Makefile20
-rw-r--r--drivers/media/video/tegra/ad5820.c231
-rw-r--r--drivers/media/video/tegra/ar0832_main.c2549
-rw-r--r--drivers/media/video/tegra/avp/Kconfig25
-rw-r--r--drivers/media/video/tegra/avp/Makefile7
-rw-r--r--drivers/media/video/tegra/avp/avp.c1949
-rw-r--r--drivers/media/video/tegra/avp/avp.h32
-rw-r--r--drivers/media/video/tegra/avp/avp_msg.h358
-rw-r--r--drivers/media/video/tegra/avp/avp_svc.c890
-rw-r--r--drivers/media/video/tegra/avp/headavp.S68
-rw-r--r--drivers/media/video/tegra/avp/headavp.h41
-rw-r--r--drivers/media/video/tegra/avp/nvavp.h53
-rw-r--r--drivers/media/video/tegra/avp/tegra_rpc.c796
-rw-r--r--drivers/media/video/tegra/avp/trpc.h80
-rw-r--r--drivers/media/video/tegra/avp/trpc_local.c419
-rw-r--r--drivers/media/video/tegra/avp/trpc_sema.c244
-rw-r--r--drivers/media/video/tegra/avp/trpc_sema.h30
-rw-r--r--drivers/media/video/tegra/mediaserver/Kconfig10
-rw-r--r--drivers/media/video/tegra/mediaserver/Makefile3
-rw-r--r--drivers/media/video/tegra/mediaserver/tegra_mediaserver.c556
-rw-r--r--drivers/media/video/tegra/nvavp/Kconfig10
-rw-r--r--drivers/media/video/tegra/nvavp/Makefile3
-rw-r--r--drivers/media/video/tegra/nvavp/nvavp_dev.c1441
-rw-r--r--drivers/media/video/tegra/nvavp/nvavp_os.h103
-rw-r--r--drivers/media/video/tegra/ov14810.c1390
-rw-r--r--drivers/media/video/tegra/ov2710.c690
-rw-r--r--drivers/media/video/tegra/ov5650.c1520
-rw-r--r--drivers/media/video/tegra/ov9726.c845
-rw-r--r--drivers/media/video/tegra/sh532u.c1688
-rw-r--r--drivers/media/video/tegra/soc380.c473
-rw-r--r--drivers/media/video/tegra/ssl3250a.c986
-rw-r--r--drivers/media/video/tegra/tegra_camera.c612
-rw-r--r--drivers/media/video/tegra/tegra_dtv.c1089
-rw-r--r--drivers/media/video/tegra/tps61050.c991
35 files changed, 20292 insertions, 0 deletions
diff --git a/drivers/media/video/tegra/Kconfig b/drivers/media/video/tegra/Kconfig
new file mode 100644
index 00000000000..404d771a717
--- /dev/null
+++ b/drivers/media/video/tegra/Kconfig
@@ -0,0 +1,90 @@
1source "drivers/media/video/tegra/avp/Kconfig"
2source "drivers/media/video/tegra/mediaserver/Kconfig"
3source "drivers/media/video/tegra/nvavp/Kconfig"
4
5config TEGRA_CAMERA
6 bool "Enable support for tegra camera/isp hardware"
7 depends on ARCH_TEGRA
8 default y
9 help
10 Enables support for the Tegra camera interface
11
12 If unsure, say Y
13
14config TEGRA_DTV
15 bool "Enable support for tegra dtv interface"
16 depends on ARCH_TEGRA
17 default y
18 help
19 Enables support for the Tegra dtv interface
20
21 If unsure, say Y
22
23config VIDEO_OV5650
24 tristate "OV5650 camera sensor support"
25 depends on I2C && ARCH_TEGRA
26 ---help---
27 This is a driver for the Omnivision OV5650 5MP camera sensor
28 for use with the tegra isp.
29
30config VIDEO_OV14810
31 tristate "OV14810 camera sensor support"
32 depends on I2C && ARCH_TEGRA
33 ---help---
34 This is a driver for the Omnivision OV14810 14MP camera sensor
35 for use with the tegra isp.
36
37
38config VIDEO_OV9726
39 tristate "OV9726 camera sensor support"
40 depends on I2C && ARCH_TEGRA
41 ---help---
42 This is a driver for the Omnivision OV9726 camera sensor
43 for use with the tegra isp.
44
45config VIDEO_OV2710
46 tristate "OV2710 camera sensor support"
47 depends on I2C && ARCH_TEGRA
48 ---help---
49 This is a driver for the Omnivision OV2710 camera sensor
50 for use with the tegra isp.
51
52config VIDEO_AR0832
53 tristate "AR0832 camera sensor support"
54 depends on I2C && ARCH_TEGRA
55 ---help---
56 This is a driver for the AR0832 camera sensor
57 for use with the tegra isp.
58
59config VIDEO_SOC380
60 tristate "SOC380 camera sensor support"
61 depends on I2C && ARCH_TEGRA
62 ---help---
63 This is a driver for the Semco soc380 camera sensor
64 for use with the tegra isp.
65
66config TORCH_SSL3250A
67 tristate "SSL3250A flash/torch support"
68 depends on I2C && ARCH_TEGRA
69 ---help---
70 This is a driver for the SSL3250A flash/torch camera device
71
72config TORCH_TPS61050
73 tristate "TPS61050 flash/torch support"
74 depends on I2C && ARCH_TEGRA
75 ---help---
76 This is a driver for the TPS61050 flash/torch camera device
77
78config VIDEO_SH532U
79 tristate "SH532U focuser support"
80 depends on I2C && ARCH_TEGRA
81 ---help---
82 This is a driver for the SEMCO SH532U focuser
83 for use with the tegra isp.
84
85config VIDEO_AD5820
86 tristate "AD5820 focuser support"
87 depends on I2C && ARCH_TEGRA
88 ---help---
89 This is a driver for the AD5820 focuser
90 for use with the tegra isp.
diff --git a/drivers/media/video/tegra/Makefile b/drivers/media/video/tegra/Makefile
new file mode 100644
index 00000000000..5d404e44fd2
--- /dev/null
+++ b/drivers/media/video/tegra/Makefile
@@ -0,0 +1,20 @@
1GCOV_PROFILE := y
2#
3# Makefile for the video capture/playback device drivers.
4#
5obj-y += avp/
6obj-$(CONFIG_TEGRA_MEDIASERVER) += mediaserver/
7obj-$(CONFIG_TEGRA_NVAVP) += nvavp/
8obj-$(CONFIG_TEGRA_DTV) += tegra_dtv.o
9obj-$(CONFIG_TEGRA_CAMERA) += tegra_camera.o
10obj-$(CONFIG_VIDEO_AR0832) += ar0832_main.o
11obj-$(CONFIG_VIDEO_OV5650) += ov5650.o
12obj-$(CONFIG_VIDEO_OV14810) += ov14810.o
13obj-$(CONFIG_VIDEO_OV9726) += ov9726.o
14obj-$(CONFIG_VIDEO_OV2710) += ov2710.o
15obj-$(CONFIG_VIDEO_SOC380) += soc380.o
16obj-$(CONFIG_TORCH_SSL3250A) += ssl3250a.o
17obj-$(CONFIG_TORCH_TPS61050) += tps61050.o
18obj-$(CONFIG_VIDEO_SH532U) += sh532u.o
19obj-$(CONFIG_VIDEO_AD5820) += ad5820.o
20
diff --git a/drivers/media/video/tegra/ad5820.c b/drivers/media/video/tegra/ad5820.c
new file mode 100644
index 00000000000..19d35bca5b0
--- /dev/null
+++ b/drivers/media/video/tegra/ad5820.c
@@ -0,0 +1,231 @@
1/*
2 * AD5820 focuser driver.
3 *
4 * Copyright (C) 2010-2011 NVIDIA Corporation.
5 *
6 * Contributors:
7 * Sachin Nikam <snikam@nvidia.com>
8 *
9 * Based on ov5650.c.
10 *
11 * This file is licensed under the terms of the GNU General Public License
12 * version 2. This program is licensed "as is" without any warranty of any
13 * kind, whether express or implied.
14 */
15
16#include <linux/delay.h>
17#include <linux/fs.h>
18#include <linux/i2c.h>
19#include <linux/miscdevice.h>
20#include <linux/regulator/consumer.h>
21#include <linux/slab.h>
22#include <linux/uaccess.h>
23#include <media/ad5820.h>
24
25/* Focuser single step & full scale transition time truth table
26 * in the format of:
27 * index mode single step transition full scale transition
28 * 0 0 0 0
29 * 1 1 50uS 51.2mS
30 * 2 1 100uS 102.3mS
31 * 3 1 200uS 204.6mS
32 * 4 1 400uS 409.2mS
33 * 5 1 800uS 818.4mS
34 * 6 1 1600uS 1636.8mS
35 * 7 1 3200uS 3273.6mS
36 * 8 0 0 0
37 * 9 2 50uS 1.1mS
38 * A 2 100uS 2.2mS
39 * B 2 200uS 4.4mS
40 * C 2 400uS 8.8mS
41 * D 2 800uS 17.6mS
42 * E 2 1600uS 35.2mS
43 * F 2 3200uS 70.4mS
44 */
45
46/* pick up the mode index setting and its settle time from the above table */
47#define AD5820_TRANSITION_MODE 0x0B
48#define SETTLETIME_MS 5
49
50#define POS_LOW (0)
51#define POS_HIGH (1023)
52#define FOCAL_LENGTH (4.507f)
53#define FNUMBER (2.8f)
54#define FPOS_COUNT 1024
55
56struct ad5820_info {
57 struct i2c_client *i2c_client;
58 struct regulator *regulator;
59 struct ad5820_config config;
60};
61
62static int ad5820_write(struct i2c_client *client, u32 value)
63{
64 int count;
65 struct i2c_msg msg[1];
66 unsigned char data[2];
67
68 if (!client->adapter)
69 return -ENODEV;
70
71 data[0] = (u8) ((value >> 4) & 0x3F);
72 data[1] = (u8) ((value & 0xF) << 4) | AD5820_TRANSITION_MODE;
73
74 msg[0].addr = client->addr;
75 msg[0].flags = 0;
76 msg[0].len = ARRAY_SIZE(data);
77 msg[0].buf = data;
78
79 count = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
80 if (count == ARRAY_SIZE(msg))
81 return 0;
82
83 return -EIO;
84}
85
86static int ad5820_set_position(struct ad5820_info *info, u32 position)
87{
88 if (position < info->config.pos_low ||
89 position > info->config.pos_high)
90 return -EINVAL;
91
92 return ad5820_write(info->i2c_client, position);
93}
94
95static long ad5820_ioctl(struct file *file,
96 unsigned int cmd, unsigned long arg)
97{
98 struct ad5820_info *info = file->private_data;
99
100 switch (cmd) {
101 case AD5820_IOCTL_GET_CONFIG:
102 {
103 if (copy_to_user((void __user *) arg,
104 &info->config,
105 sizeof(info->config))) {
106 pr_err("%s: 0x%x\n", __func__, __LINE__);
107 return -EFAULT;
108 }
109
110 break;
111 }
112 case AD5820_IOCTL_SET_POSITION:
113 return ad5820_set_position(info, (u32) arg);
114 default:
115 return -EINVAL;
116 }
117
118 return 0;
119}
120
121struct ad5820_info *info;
122
123static int ad5820_open(struct inode *inode, struct file *file)
124{
125 file->private_data = info;
126 if (info->regulator)
127 regulator_enable(info->regulator);
128 return 0;
129}
130
131int ad5820_release(struct inode *inode, struct file *file)
132{
133 if (info->regulator)
134 regulator_disable(info->regulator);
135 file->private_data = NULL;
136 return 0;
137}
138
139
140static const struct file_operations ad5820_fileops = {
141 .owner = THIS_MODULE,
142 .open = ad5820_open,
143 .unlocked_ioctl = ad5820_ioctl,
144 .release = ad5820_release,
145};
146
147static struct miscdevice ad5820_device = {
148 .minor = MISC_DYNAMIC_MINOR,
149 .name = "ad5820",
150 .fops = &ad5820_fileops,
151};
152
153static int ad5820_probe(struct i2c_client *client,
154 const struct i2c_device_id *id)
155{
156 int err;
157
158 pr_info("ad5820: probing sensor.\n");
159
160 info = kzalloc(sizeof(struct ad5820_info), GFP_KERNEL);
161 if (!info) {
162 pr_err("ad5820: Unable to allocate memory!\n");
163 return -ENOMEM;
164 }
165
166 err = misc_register(&ad5820_device);
167 if (err) {
168 pr_err("ad5820: Unable to register misc device!\n");
169 kfree(info);
170 return err;
171 }
172
173 info->regulator = regulator_get(&client->dev, "vdd_vcore_af");
174 if (IS_ERR_OR_NULL(info->regulator)) {
175 dev_err(&client->dev, "unable to get regulator %s\n",
176 dev_name(&client->dev));
177 info->regulator = NULL;
178 } else {
179 regulator_enable(info->regulator);
180 }
181
182 info->i2c_client = client;
183 info->config.settle_time = SETTLETIME_MS;
184 info->config.focal_length = FOCAL_LENGTH;
185 info->config.fnumber = FNUMBER;
186 info->config.pos_low = POS_LOW;
187 info->config.pos_high = POS_HIGH;
188 i2c_set_clientdata(client, info);
189 return 0;
190}
191
192static int ad5820_remove(struct i2c_client *client)
193{
194 struct ad5820_info *info;
195 info = i2c_get_clientdata(client);
196 misc_deregister(&ad5820_device);
197 kfree(info);
198 return 0;
199}
200
201static const struct i2c_device_id ad5820_id[] = {
202 { "ad5820", 0 },
203 { },
204};
205
206MODULE_DEVICE_TABLE(i2c, ad5820_id);
207
208static struct i2c_driver ad5820_i2c_driver = {
209 .driver = {
210 .name = "ad5820",
211 .owner = THIS_MODULE,
212 },
213 .probe = ad5820_probe,
214 .remove = ad5820_remove,
215 .id_table = ad5820_id,
216};
217
218static int __init ad5820_init(void)
219{
220 pr_info("ad5820 sensor driver loading\n");
221 return i2c_add_driver(&ad5820_i2c_driver);
222}
223
224static void __exit ad5820_exit(void)
225{
226 i2c_del_driver(&ad5820_i2c_driver);
227}
228
229module_init(ad5820_init);
230module_exit(ad5820_exit);
231
diff --git a/drivers/media/video/tegra/ar0832_main.c b/drivers/media/video/tegra/ar0832_main.c
new file mode 100644
index 00000000000..129825cd5f8
--- /dev/null
+++ b/drivers/media/video/tegra/ar0832_main.c
@@ -0,0 +1,2549 @@
1/*
2* ar0832_main.c - Aptina AR0832 8M Bayer type sensor driver
3*
4* Copyright (c) 2011, NVIDIA, All Rights Reserved.
5*
6* This file is licensed under the terms of the GNU General Public License
7* version 2. This program is licensed "as is" without any warranty of any
8* kind, whether express or implied.
9*/
10
11#include <linux/kernel.h>
12#include <linux/delay.h>
13#include <linux/fs.h>
14#include <linux/i2c.h>
15#include <linux/miscdevice.h>
16#include <linux/slab.h>
17#include <linux/uaccess.h>
18#include <mach/hardware.h>
19#include <linux/gpio.h>
20#include <linux/debugfs.h>
21#include <linux/seq_file.h>
22#include <asm/atomic.h>
23#include <linux/regulator/consumer.h>
24#include <media/ar0832_main.h>
25
26#define POS_LOW 0
27#define POS_HIGH 1000
28#define SETTLETIME_MS 100
29
30struct ar0832_sensor_info {
31 int mode;
32 struct ar0832_stereo_region region;
33};
34
35struct ar0832_focuser_info {
36 struct ar0832_focuser_config config;
37 int focuser_init_flag;
38 u16 last_position;
39};
40
41struct ar0832_power_rail {
42 struct regulator *sen_1v8_reg;
43 struct regulator *sen_2v8_reg;
44};
45
46struct ar0832_dev {
47 struct ar0832_sensor_info *sensor_info;
48 struct ar0832_focuser_info *focuser_info;
49 struct ar0832_platform_data *pdata;
50 struct i2c_client *i2c_client;
51 struct mutex ar0832_camera_lock;
52 struct miscdevice misc_dev;
53 struct ar0832_power_rail power_rail;
54 int brd_power_cnt;
55 atomic_t in_use;
56 char dname[20];
57 int is_stereo;
58 u16 sensor_id_data;
59 struct dentry *debugdir;
60};
61
62#define UpperByte16to8(x) ((u8)((x & 0xFF00) >> 8))
63#define LowerByte16to8(x) ((u8)(x & 0x00FF))
64
65#define ar0832_TABLE_WAIT_MS 0
66#define ar0832_TABLE_END 1
67#define ar0832_MAX_RETRIES 3
68
69/* AR0832 Register */
70#define AR0832_SENSORID_REG 0x0002
71#define AR0832_RESET_REG 0x301A
72#define AR0832_ID_REG 0x31FC
73#define AR0832_GLOBAL_GAIN_REG 0x305E
74#define AR0832_TEST_PATTERN_REG 0x0600
75#define AR0832_GROUP_HOLD_REG 0x0104
76#define AR0832_TEST_RED_REG 0x0602
77#define AR0832_TEST_GREENR_REG 0x0604
78#define AR0832_TEST_BLUE_REG 0x0606
79#define AR0832_TEST_GREENB_REG 0x0608
80
81
82
83/* AR0832_RESET_REG */
84#define AR0832_RESET_REG_GROUPED_PARAMETER_HOLD (1 << 15)
85#define AR0832_RESET_REG_GAIN_INSERT (1 << 14)
86#define AR0832_RESET_REG_SMIA_SERIALIZER_DIS (1 << 12)
87#define AR0832_RESET_REG_RESTART_BAD (1 << 10)
88#define AR0832_RESET_REG_MASK_BAD (1 << 9)
89#define AR0832_RESET_REG_GPI_EN (1 << 8)
90#define AR0832_RESET_REG_PARALLEL_EN (1 << 7)
91#define AR0832_RESET_REG_DRIVE_PINS (1 << 6)
92#define AR0832_RESET_REG_STDBY_EOF (1 << 4)
93#define AR0832_RESET_REG_LOCK_REG (1 << 3)
94#define AR0832_RESET_REG_STREAM (1 << 2)
95#define AR0832_RESET_REG_RESTART (1 << 1)
96#define AR0832_RESET_REG_RESET (1 << 0)
97
98static struct ar0832_reg mode_start[] = {
99 {ar0832_TABLE_END, 0x0000}
100};
101
102static struct ar0832_reg mode_3264X2448_8140[] = {
103 /* mode start */
104 {0x301A, 0x0058}, /* RESET_REGISTER */
105 {0x301A, 0x0050}, /* RESET_REGISTER */
106 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
107 {0x3064, 0x7800}, /* RESERVED_MFR_3064 */
108 {0x31AE, 0x0202}, /* SERIAL_FORMAT */
109 /* MT9E013 Recommended Settings */
110 {0x31B0, 0x0083}, /* FRAME_PREAMBLE */
111 {0x31B2, 0x004D}, /* LINE_PREAMBLE */
112 {0x31B4, 0x0E77}, /* MIPI_TIMING_0 */
113 {0x31B6, 0x0D20}, /* MIPI_TIMING_1 */
114 {0x31B8, 0x020E}, /* MIPI_TIMING_2 */
115 {0x31BA, 0x0710}, /* MIPI_TIMING_3 */
116 {0x31BC, 0x2A0D}, /* MIPI_TIMING_4 */
117 {ar0832_TABLE_WAIT_MS, 0x0005},
118 {0x0112, 0x0A0A}, /* CCP_DATA_FORMAT */
119 {0x3044, 0x0590},
120 {0x306E, 0xFC80},
121 {0x30B2, 0xC000},
122 {0x30D6, 0x0800},
123 {0x316C, 0xB42F},
124 {0x316E, 0x869A},
125 {0x3170, 0x210E},
126 {0x317A, 0x010E},
127 {0x31E0, 0x1FB9},
128 {0x31E6, 0x07FC},
129 {0x37C0, 0x0000},
130 {0x37C2, 0x0000},
131 {0x37C4, 0x0000},
132 {0x37C6, 0x0000},
133 {0x3E00, 0x0011},
134 {0x3E02, 0x8801},
135 {0x3E04, 0x2801},
136 {0x3E06, 0x8449},
137 {0x3E08, 0x6841},
138 {0x3E0A, 0x400C},
139 {0x3E0C, 0x1001},
140 {0x3E0E, 0x2603},
141 {0x3E10, 0x4B41},
142 {0x3E12, 0x4B24},
143 {0x3E14, 0xA3CF},
144 {0x3E16, 0x8802},
145 {0x3E18, 0x8401},
146 {0x3E1A, 0x8601},
147 {0x3E1C, 0x8401},
148 {0x3E1E, 0x840A},
149 {0x3E20, 0xFF00},
150 {0x3E22, 0x8401},
151 {0x3E24, 0x00FF},
152 {0x3E26, 0x0088},
153 {0x3E28, 0x2E8A},
154 {0x3E30, 0x0000},
155 {0x3E32, 0x8801},
156 {0x3E34, 0x4029},
157 {0x3E36, 0x00FF},
158 {0x3E38, 0x8469},
159 {0x3E3A, 0x00FF},
160 {0x3E3C, 0x2801},
161 {0x3E3E, 0x3E2A},
162 {0x3E40, 0x1C01},
163 {0x3E42, 0xFF84},
164 {0x3E44, 0x8401},
165 {0x3E46, 0x0C01},
166 {0x3E48, 0x8401},
167 {0x3E4A, 0x00FF},
168 {0x3E4C, 0x8402},
169 {0x3E4E, 0x8984},
170 {0x3E50, 0x6628},
171 {0x3E52, 0x8340},
172 {0x3E54, 0x00FF},
173 {0x3E56, 0x4A42},
174 {0x3E58, 0x2703},
175 {0x3E5A, 0x6752},
176 {0x3E5C, 0x3F2A},
177 {0x3E5E, 0x846A},
178 {0x3E60, 0x4C01},
179 {0x3E62, 0x8401},
180 {0x3E66, 0x3901},
181 {0x3E90, 0x2C01},
182 {0x3E98, 0x2B02},
183 {0x3E92, 0x2A04},
184 {0x3E94, 0x2509},
185 {0x3E96, 0x0000},
186 {0x3E9A, 0x2905},
187 {0x3E9C, 0x00FF},
188 {0x3ECC, 0x00EB},
189 {0x3ED0, 0x1E24},
190 {0x3ED4, 0xAFC4},
191 {0x3ED6, 0x909B},
192 {0x3EE0, 0x2424},
193 {0x3EE2, 0x9797},
194 {0x3EE4, 0xC100},
195 {0x3EE6, 0x0540},
196 {0x3174, 0x8000},
197
198 /* mode end */
199 {0x0300, 0x0004}, /* VT_PIX_CLK_DIV */
200 {0x0302, 0x0001}, /* VT_SYS_CLK_DIV */
201 {0x0304, 0x0002}, /* PRE_PLL_CLK_DIV */
202 {0x0306, 0x0040}, /* PLL_MULTIPLIER */
203 {0x0308, 0x000A}, /* OP_PIX_CLK_DIV */
204 {0x030A, 0x0001}, /* OP_SYS_CLK_DIV */
205 {ar0832_TABLE_WAIT_MS, 0x0001},
206 {0x3064, 0x7400}, /* RESERVED_MFR_3064 */
207 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
208 {0x0344, 0x0004}, /* X_ADDR_START */
209 {0x0348, 0x0CCB}, /* X_ADDR_END */
210 {0x0346, 0x0004}, /* Y_ADDR_START */
211 {0x034A, 0x099B}, /* Y_ADDR_END */
212 {0x034C, 0x0CC8}, /* X_OUTPUT_SIZE */
213 {0x034E, 0x0998}, /* Y_OUTPUT_SIZE */
214 {0x3040, 0xC041}, /* READ_MODE */
215 {0x306E, 0xFC80}, /* DATAPATH_SELECT */
216 {0x0400, 0x0000}, /* SCALING_MODE */
217 {0x0404, 0x0010}, /* SCALE_M */
218 {0x3178, 0x0000}, /* RESERVED_MFR_3178 */
219 {0x3ED0, 0x1E24}, /* RESERVED_MFR_3ED0 */
220 {0x0400, 0x0000}, /* SCALING_MODE */
221 {0x0404, 0x0010}, /* SCALE_M */
222 {0x0342, 0x133C}, /* LINE_LENGTH_PCK */
223 {0x0340, 0x0A27}, /* FRAME_LENGTH_LINES */
224 {0x0202, 0x0A27}, /* COARSE_INTEGRATION_TIME */
225 {0x3014, 0x09DC}, /* FINE_INTEGRATION_TIME */
226 {0x3010, 0x0078}, /* FINE_CORRECTION */
227 {0x301A, 0x8250}, /* RESET_REGISTER */
228 {0x301A, 0x8650}, /* RESET_REGISTER */
229 {0x301A, 0x8658}, /* RESET_REGISTER */
230 /* gain */
231 {0x305e, 0x10AA}, /* gain */
232 {0x0104, 0x0000}, /* GROUPED_PARAMETER_HOLD */
233 {0x301A, 0x065C}, /* RESET_REGISTER */
234 {ar0832_TABLE_END, 0x0000}
235};
236
237static struct ar0832_reg mode_3264X2448_8141[] = {
238 /* mode start */
239 {0x301A, 0x0058}, /* RESET_REGISTER */
240 {0x301A, 0x0050}, /* RESET_REGISTER */
241 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
242 {0x3064, 0x7800}, /* RESERVED_MFR_3064 */
243 {0x31AE, 0x0202}, /* SERIAL_FORMAT */
244 /* AR0832 Recommended Settings */
245 {0x3044, 0x0590},
246 {0x306E, 0xFC80},
247 {0x30B2, 0xC000},
248 {0x30D6, 0x0800},
249 {0x316C, 0xB42F},
250 {0x316E, 0x869A},
251 {0x3170, 0x210E},
252 {0x317A, 0x010E},
253 {0x31E0, 0x1FB9},
254 {0x31E6, 0x07FC},
255 {0x37C0, 0x0000},
256 {0x37C2, 0x0000},
257 {0x37C4, 0x0000},
258 {0x37C6, 0x0000},
259 {0x3E00, 0x0011},
260 {0x3E02, 0x8801},
261 {0x3E04, 0x2801},
262 {0x3E06, 0x8449},
263 {0x3E08, 0x6841},
264 {0x3E0A, 0x400C},
265 {0x3E0C, 0x1001},
266 {0x3E0E, 0x2603},
267 {0x3E10, 0x4B41},
268 {0x3E12, 0x4B24},
269 {0x3E14, 0xA3CF},
270 {0x3E16, 0x8802},
271 {0x3E18, 0x8401},
272 {0x3E1A, 0x8601},
273 {0x3E1C, 0x8401},
274 {0x3E1E, 0x840A},
275 {0x3E20, 0xFF00},
276 {0x3E22, 0x8401},
277 {0x3E24, 0x00FF},
278 {0x3E26, 0x0088},
279 {0x3E28, 0x2E8A},
280 {0x3E30, 0x0000},
281 {0x3E32, 0x8801},
282 {0x3E34, 0x4029},
283 {0x3E36, 0x00FF},
284 {0x3E38, 0x8469},
285 {0x3E3A, 0x00FF},
286 {0x3E3C, 0x2801},
287 {0x3E3E, 0x3E2A},
288 {0x3E40, 0x1C01},
289 {0x3E42, 0xFF84},
290 {0x3E44, 0x8401},
291 {0x3E46, 0x0C01},
292 {0x3E48, 0x8401},
293 {0x3E4A, 0x00FF},
294 {0x3E4C, 0x8402},
295 {0x3E4E, 0x8984},
296 {0x3E50, 0x6628},
297 {0x3E52, 0x8340},
298 {0x3E54, 0x00FF},
299 {0x3E56, 0x4A42},
300 {0x3E58, 0x2703},
301 {0x3E5A, 0x6752},
302 {0x3E5C, 0x3F2A},
303 {0x3E5E, 0x846A},
304 {0x3E60, 0x4C01},
305 {0x3E62, 0x8401},
306 {0x3E66, 0x3901},
307 {0x3E90, 0x2C01},
308 {0x3E98, 0x2B02},
309 {0x3E92, 0x2A04},
310 {0x3E94, 0x2509},
311 {0x3E96, 0x0000},
312 {0x3E9A, 0x2905},
313 {0x3E9C, 0x00FF},
314 {0x3ECC, 0x00EB},
315 {0x3ED0, 0x1E24},
316 {0x3ED4, 0xAFC4},
317 {0x3ED6, 0x909B},
318 {0x3EE0, 0x2424},
319 {0x3EE2, 0x9797},
320 {0x3EE4, 0xC100},
321 {0x3EE6, 0x0540},
322 {0x3174, 0x8000},
323
324 /* mode end */
325 {0x0300, 0x0004}, /* VT_PIX_CLK_DIV */
326 {0x0302, 0x0001}, /* VT_SYS_CLK_DIV */
327 {0x0304, 0x0002}, /* PRE_PLL_CLK_DIV */
328 {0x0306, 0x0040}, /* PLL_MULTIPLIER */
329 {0x0308, 0x000A}, /* OP_PIX_CLK_DIV */
330 {0x030A, 0x0001}, /* OP_SYS_CLK_DIV */
331 {ar0832_TABLE_WAIT_MS, 0x0001},
332 {0x3064, 0x7400}, /* RESERVED_MFR_3064 */
333 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
334 {0x0344, 0x0004}, /* X_ADDR_START */
335 {0x0348, 0x0CCB}, /* X_ADDR_END */
336 {0x0346, 0x0004}, /* Y_ADDR_START */
337 {0x034A, 0x099B}, /* Y_ADDR_END */
338 {0x034C, 0x0CC8}, /* X_OUTPUT_SIZE */
339 {0x034E, 0x0998}, /* Y_OUTPUT_SIZE */
340 {0x3040, 0xC041}, /* READ_MODE */
341 {0x306E, 0xFC80}, /* DATAPATH_SELECT */
342 {0x0400, 0x0000}, /* SCALING_MODE */
343 {0x0404, 0x0010}, /* SCALE_M */
344 {0x3178, 0x0000}, /* RESERVED_MFR_3178 */
345 {0x3ED0, 0x1E24}, /* RESERVED_MFR_3ED0 */
346 {0x0400, 0x0000}, /* SCALING_MODE */
347 {0x0404, 0x0010}, /* SCALE_M */
348 {0x0342, 0x133C}, /* LINE_LENGTH_PCK */
349 {0x0340, 0x0A27}, /* FRAME_LENGTH_LINES */
350 {0x0202, 0x0A27}, /* COARSE_INTEGRATION_TIME */
351 {0x3014, 0x09DC}, /* FINE_INTEGRATION_TIME */
352 {0x3010, 0x0078}, /* FINE_CORRECTION */
353 {0x301A, 0x8250}, /* RESET_REGISTER */
354 {0x301A, 0x8650}, /* RESET_REGISTER */
355 {0x301A, 0x8658}, /* RESET_REGISTER */
356 /* gain */
357 {0x305e, 0x10AA}, /* gain */
358 {0x0104, 0x0000}, /* GROUPED_PARAMETER_HOLD */
359 {0x301A, 0x065C}, /* RESET_REGISTER */
360 {ar0832_TABLE_END, 0x0000}
361};
362
363static struct ar0832_reg mode_2880X1620_8140[] = {
364 /* mode start */
365 {0x301A, 0x0058}, /* RESET_REGISTER */
366 {0x301A, 0x0050}, /* RESET_REGISTER */
367 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
368 {0x3064, 0x7800}, /* RESERVED_MFR_3064 */
369 {0x31AE, 0x0202}, /* SERIAL_FORMAT */
370 /* MT9E013 Recommended Settings */
371 {0x31B0, 0x0083}, /* FRAME_PREAMBLE */
372 {0x31B2, 0x004D}, /* LINE_PREAMBLE */
373 {0x31B4, 0x0E77}, /* MIPI_TIMING_0 */
374 {0x31B6, 0x0D20}, /* MIPI_TIMING_1 */
375 {0x31B8, 0x020E}, /* MIPI_TIMING_2 */
376 {0x31BA, 0x0710}, /* MIPI_TIMING_3 */
377 {0x31BC, 0x2A0D}, /* MIPI_TIMING_4 */
378 {ar0832_TABLE_WAIT_MS, 0x0005},
379 {0x0112, 0x0A0A}, /* CCP_DATA_FORMAT */
380 {0x3044, 0x0590},
381 {0x306E, 0xFC80},
382 {0x30B2, 0xC000},
383 {0x30D6, 0x0800},
384 {0x316C, 0xB42F},
385 {0x316E, 0x869A},
386 {0x3170, 0x210E},
387 {0x317A, 0x010E},
388 {0x31E0, 0x1FB9},
389 {0x31E6, 0x07FC},
390 {0x37C0, 0x0000},
391 {0x37C2, 0x0000},
392 {0x37C4, 0x0000},
393 {0x37C6, 0x0000},
394 {0x3E00, 0x0011},
395 {0x3E02, 0x8801},
396 {0x3E04, 0x2801},
397 {0x3E06, 0x8449},
398 {0x3E08, 0x6841},
399 {0x3E0A, 0x400C},
400 {0x3E0C, 0x1001},
401 {0x3E0E, 0x2603},
402 {0x3E10, 0x4B41},
403 {0x3E12, 0x4B24},
404 {0x3E14, 0xA3CF},
405 {0x3E16, 0x8802},
406 {0x3E18, 0x8401},
407 {0x3E1A, 0x8601},
408 {0x3E1C, 0x8401},
409 {0x3E1E, 0x840A},
410 {0x3E20, 0xFF00},
411 {0x3E22, 0x8401},
412 {0x3E24, 0x00FF},
413 {0x3E26, 0x0088},
414 {0x3E28, 0x2E8A},
415 {0x3E30, 0x0000},
416 {0x3E32, 0x8801},
417 {0x3E34, 0x4029},
418 {0x3E36, 0x00FF},
419 {0x3E38, 0x8469},
420 {0x3E3A, 0x00FF},
421 {0x3E3C, 0x2801},
422 {0x3E3E, 0x3E2A},
423 {0x3E40, 0x1C01},
424 {0x3E42, 0xFF84},
425 {0x3E44, 0x8401},
426 {0x3E46, 0x0C01},
427 {0x3E48, 0x8401},
428 {0x3E4A, 0x00FF},
429 {0x3E4C, 0x8402},
430 {0x3E4E, 0x8984},
431 {0x3E50, 0x6628},
432 {0x3E52, 0x8340},
433 {0x3E54, 0x00FF},
434 {0x3E56, 0x4A42},
435 {0x3E58, 0x2703},
436 {0x3E5A, 0x6752},
437 {0x3E5C, 0x3F2A},
438 {0x3E5E, 0x846A},
439 {0x3E60, 0x4C01},
440 {0x3E62, 0x8401},
441 {0x3E66, 0x3901},
442 {0x3E90, 0x2C01},
443 {0x3E98, 0x2B02},
444 {0x3E92, 0x2A04},
445 {0x3E94, 0x2509},
446 {0x3E96, 0x0000},
447 {0x3E9A, 0x2905},
448 {0x3E9C, 0x00FF},
449 {0x3ECC, 0x00EB},
450 {0x3ED0, 0x1E24},
451 {0x3ED4, 0xAFC4},
452 {0x3ED6, 0x909B},
453 {0x3EE0, 0x2424},
454 {0x3EE2, 0x9797},
455 {0x3EE4, 0xC100},
456 {0x3EE6, 0x0540},
457 {0x3174, 0x8000},
458
459 /* mode end */
460 {0x0300, 0x0004}, /* VT_PIX_CLK_DIV */
461 {0x0302, 0x0001}, /* VT_SYS_CLK_DIV */
462 {0x0304, 0x0002}, /* PRE_PLL_CLK_DIV */
463 {0x0306, 0x0040}, /* PLL_MULTIPLIER */
464 {0x0308, 0x000A}, /* OP_PIX_CLK_DIV */
465 {0x030A, 0x0001}, /* OP_SYS_CLK_DIV */
466 {ar0832_TABLE_WAIT_MS, 0x0001},
467 {0x3064, 0x7400}, /* RESERVED_MFR_3064 */
468 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
469 {0x0344, 0x00C8}, /* X_ADDR_START */
470 {0x0348, 0x0C07}, /* X_ADDR_END */
471 {0x0346, 0x01A6}, /* Y_ADDR_START */
472 {0x034A, 0x07F9}, /* Y_ADDR_END */
473 {0x034C, 0x0B40}, /* X_OUTPUT_SIZE */
474 {0x034E, 0x0654}, /* Y_OUTPUT_SIZE */
475 {0x3040, 0xC041}, /* READ_MODE */
476 {0x306E, 0xFC80}, /* DATAPATH_SELECT */
477 {0x0400, 0x0000}, /* SCALING_MODE */
478 {0x0404, 0x0010}, /* SCALE_M */
479 {0x3178, 0x0000}, /* RESERVED_MFR_3178 */
480 {0x3ED0, 0x1E24}, /* RESERVED_MFR_3ED0 */
481
482 {0x0342, 0x11B8}, /* LINE_LENGTH_PCK */
483 {0x0340, 0x06E3}, /* FRAME_LENGTH_LINES */
484 {0x0202, 0x06E3}, /* COARSE_INTEGRATION_TIME */
485 {0x3014, 0x0BD8}, /* FINE_INTEGRATION_TIME */
486 {0x3010, 0x0078}, /* FINE_CORRECTION */
487 {0x301A, 0x8250}, /* RESET_REGISTER */
488 {0x301A, 0x8650}, /* RESET_REGISTER */
489 {0x301A, 0x8658}, /* RESET_REGISTER */
490 /* gain */
491 {0x305e, 0x10AA}, /* gain */
492 {0x0104, 0x0000}, /* GROUPED_PARAMETER_HOLD */
493 {0x301A, 0x065C}, /* RESET_REGISTER */
494 {ar0832_TABLE_END, 0x0000}
495};
496
497static struct ar0832_reg mode_2880X1620_8141[] = {
498 /* mode start */
499 {0x301A, 0x0058}, /* RESET_REGISTER */
500 {0x301A, 0x0050}, /* RESET_REGISTER */
501 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
502 {0x3064, 0x7800}, /* RESERVED_MFR_3064 */
503 {0x31AE, 0x0202}, /* SERIAL_FORMAT */
504 /* AR0832 Recommended Settings */
505 {0x3044, 0x0590},
506 {0x306E, 0xFC80},
507 {0x30B2, 0xC000},
508 {0x30D6, 0x0800},
509 {0x316C, 0xB42F},
510 {0x316E, 0x869A},
511 {0x3170, 0x210E},
512 {0x317A, 0x010E},
513 {0x31E0, 0x1FB9},
514 {0x31E6, 0x07FC},
515 {0x37C0, 0x0000},
516 {0x37C2, 0x0000},
517 {0x37C4, 0x0000},
518 {0x37C6, 0x0000},
519 {0x3E00, 0x0011},
520 {0x3E02, 0x8801},
521 {0x3E04, 0x2801},
522 {0x3E06, 0x8449},
523 {0x3E08, 0x6841},
524 {0x3E0A, 0x400C},
525 {0x3E0C, 0x1001},
526 {0x3E0E, 0x2603},
527 {0x3E10, 0x4B41},
528 {0x3E12, 0x4B24},
529 {0x3E14, 0xA3CF},
530 {0x3E16, 0x8802},
531 {0x3E18, 0x8401},
532 {0x3E1A, 0x8601},
533 {0x3E1C, 0x8401},
534 {0x3E1E, 0x840A},
535 {0x3E20, 0xFF00},
536 {0x3E22, 0x8401},
537 {0x3E24, 0x00FF},
538 {0x3E26, 0x0088},
539 {0x3E28, 0x2E8A},
540 {0x3E30, 0x0000},
541 {0x3E32, 0x8801},
542 {0x3E34, 0x4029},
543 {0x3E36, 0x00FF},
544 {0x3E38, 0x8469},
545 {0x3E3A, 0x00FF},
546 {0x3E3C, 0x2801},
547 {0x3E3E, 0x3E2A},
548 {0x3E40, 0x1C01},
549 {0x3E42, 0xFF84},
550 {0x3E44, 0x8401},
551 {0x3E46, 0x0C01},
552 {0x3E48, 0x8401},
553 {0x3E4A, 0x00FF},
554 {0x3E4C, 0x8402},
555 {0x3E4E, 0x8984},
556 {0x3E50, 0x6628},
557 {0x3E52, 0x8340},
558 {0x3E54, 0x00FF},
559 {0x3E56, 0x4A42},
560 {0x3E58, 0x2703},
561 {0x3E5A, 0x6752},
562 {0x3E5C, 0x3F2A},
563 {0x3E5E, 0x846A},
564 {0x3E60, 0x4C01},
565 {0x3E62, 0x8401},
566 {0x3E66, 0x3901},
567 {0x3E90, 0x2C01},
568 {0x3E98, 0x2B02},
569 {0x3E92, 0x2A04},
570 {0x3E94, 0x2509},
571 {0x3E96, 0x0000},
572 {0x3E9A, 0x2905},
573 {0x3E9C, 0x00FF},
574 {0x3ECC, 0x00EB},
575 {0x3ED0, 0x1E24},
576 {0x3ED4, 0xAFC4},
577 {0x3ED6, 0x909B},
578 {0x3EE0, 0x2424},
579 {0x3EE2, 0x9797},
580 {0x3EE4, 0xC100},
581 {0x3EE6, 0x0540},
582 {0x3174, 0x8000},
583
584 /* mode end */
585 {0x0300, 0x0004}, /* VT_PIX_CLK_DIV */
586 {0x0302, 0x0001}, /* VT_SYS_CLK_DIV */
587 {0x0304, 0x0002}, /* PRE_PLL_CLK_DIV */
588 {0x0306, 0x0040}, /* PLL_MULTIPLIER */
589 {0x0308, 0x000A}, /* OP_PIX_CLK_DIV */
590 {0x030A, 0x0001}, /* OP_SYS_CLK_DIV */
591 {ar0832_TABLE_WAIT_MS, 0x0001},
592 {0x3064, 0x7400}, /* RESERVED_MFR_3064 */
593 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
594 {0x0344, 0x00C8}, /* X_ADDR_START */
595 {0x0348, 0x0C07}, /* X_ADDR_END */
596 {0x0346, 0x01A6}, /* Y_ADDR_START */
597 {0x034A, 0x07F9}, /* Y_ADDR_END */
598 {0x034C, 0x0B40}, /* X_OUTPUT_SIZE */
599 {0x034E, 0x0654}, /* Y_OUTPUT_SIZE */
600 {0x3040, 0xC041}, /* READ_MODE */
601 {0x306E, 0xFC80}, /* DATAPATH_SELECT */
602 {0x0400, 0x0000}, /* SCALING_MODE */
603 {0x0404, 0x0010}, /* SCALE_M */
604 {0x3178, 0x0000}, /* RESERVED_MFR_3178 */
605 {0x3ED0, 0x1E24}, /* RESERVED_MFR_3ED0 */
606
607 {0x0342, 0x11B8}, /* LINE_LENGTH_PCK */
608 {0x0340, 0x06E3}, /* FRAME_LENGTH_LINES */
609 {0x0202, 0x06E3}, /* COARSE_INTEGRATION_TIME */
610 {0x3014, 0x0BD8}, /* FINE_INTEGRATION_TIME */
611 {0x3010, 0x0078}, /* FINE_CORRECTION */
612 {0x301A, 0x8250}, /* RESET_REGISTER */
613 {0x301A, 0x8650}, /* RESET_REGISTER */
614 {0x301A, 0x8658}, /* RESET_REGISTER */
615 /* gain */
616 {0x305e, 0x10AA}, /* gain */
617 {0x0104, 0x0000}, /* GROUPED_PARAMETER_HOLD */
618 {0x301A, 0x065C}, /* RESET_REGISTER */
619 {ar0832_TABLE_END, 0x0000}
620};
621
622static struct ar0832_reg mode_1920X1080_8140[] = {
623 /* mode start */
624 {0x301A, 0x0058}, /* RESET_REGISTER */
625 {0x301A, 0x0050}, /* RESET_REGISTER */
626 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
627 {0x3064, 0x7800}, /* RESERVED_MFR_3064 */
628 {0x31AE, 0x0202}, /* SERIAL_FORMAT */
629 /* MT9E013 Recommended Settings */
630 {0x31B0, 0x0083}, /* FRAME_PREAMBLE */
631 {0x31B2, 0x004D}, /* LINE_PREAMBLE */
632 {0x31B4, 0x0E77}, /* MIPI_TIMING_0 */
633 {0x31B6, 0x0D20}, /* MIPI_TIMING_1 */
634 {0x31B8, 0x020E}, /* MIPI_TIMING_2 */
635 {0x31BA, 0x0710}, /* MIPI_TIMING_3 */
636 {0x31BC, 0x2A0D}, /* MIPI_TIMING_4 */
637 {ar0832_TABLE_WAIT_MS, 0x0005},
638 {0x0112, 0x0A0A}, /* CCP_DATA_FORMAT */
639 {0x3044, 0x0590},
640 {0x306E, 0xFC80},
641 {0x30B2, 0xC000},
642 {0x30D6, 0x0800},
643 {0x316C, 0xB42F},
644 {0x316E, 0x869A},
645 {0x3170, 0x210E},
646 {0x317A, 0x010E},
647 {0x31E0, 0x1FB9},
648 {0x31E6, 0x07FC},
649 {0x37C0, 0x0000},
650 {0x37C2, 0x0000},
651 {0x37C4, 0x0000},
652 {0x37C6, 0x0000},
653 {0x3E00, 0x0011},
654 {0x3E02, 0x8801},
655 {0x3E04, 0x2801},
656 {0x3E06, 0x8449},
657 {0x3E08, 0x6841},
658 {0x3E0A, 0x400C},
659 {0x3E0C, 0x1001},
660 {0x3E0E, 0x2603},
661 {0x3E10, 0x4B41},
662 {0x3E12, 0x4B24},
663 {0x3E14, 0xA3CF},
664 {0x3E16, 0x8802},
665 {0x3E18, 0x8401},
666 {0x3E1A, 0x8601},
667 {0x3E1C, 0x8401},
668 {0x3E1E, 0x840A},
669 {0x3E20, 0xFF00},
670 {0x3E22, 0x8401},
671 {0x3E24, 0x00FF},
672 {0x3E26, 0x0088},
673 {0x3E28, 0x2E8A},
674 {0x3E30, 0x0000},
675 {0x3E32, 0x8801},
676 {0x3E34, 0x4029},
677 {0x3E36, 0x00FF},
678 {0x3E38, 0x8469},
679 {0x3E3A, 0x00FF},
680 {0x3E3C, 0x2801},
681 {0x3E3E, 0x3E2A},
682 {0x3E40, 0x1C01},
683 {0x3E42, 0xFF84},
684 {0x3E44, 0x8401},
685 {0x3E46, 0x0C01},
686 {0x3E48, 0x8401},
687 {0x3E4A, 0x00FF},
688 {0x3E4C, 0x8402},
689 {0x3E4E, 0x8984},
690 {0x3E50, 0x6628},
691 {0x3E52, 0x8340},
692 {0x3E54, 0x00FF},
693 {0x3E56, 0x4A42},
694 {0x3E58, 0x2703},
695 {0x3E5A, 0x6752},
696 {0x3E5C, 0x3F2A},
697 {0x3E5E, 0x846A},
698 {0x3E60, 0x4C01},
699 {0x3E62, 0x8401},
700 {0x3E66, 0x3901},
701 {0x3E90, 0x2C01},
702 {0x3E98, 0x2B02},
703 {0x3E92, 0x2A04},
704 {0x3E94, 0x2509},
705 {0x3E96, 0x0000},
706 {0x3E9A, 0x2905},
707 {0x3E9C, 0x00FF},
708 {0x3ECC, 0x00EB},
709 {0x3ED0, 0x1E24},
710 {0x3ED4, 0xAFC4},
711 {0x3ED6, 0x909B},
712 {0x3EE0, 0x2424},
713 {0x3EE2, 0x9797},
714 {0x3EE4, 0xC100},
715 {0x3EE6, 0x0540},
716 {0x3174, 0x8000},
717
718 /* mode end */
719 {0x0300, 0x0004}, /* VT_PIX_CLK_DIV */
720 {0x0302, 0x0001}, /* VT_SYS_CLK_DIV */
721 {0x0304, 0x0002}, /* PRE_PLL_CLK_DIV */
722 {0x0306, 0x0040}, /* PLL_MULTIPLIER */
723 {0x0308, 0x000A}, /* OP_PIX_CLK_DIV */
724 {0x030A, 0x0001}, /* OP_SYS_CLK_DIV */
725 {ar0832_TABLE_WAIT_MS, 0x0001},
726 {0x3064, 0x7400}, /* RESERVED_MFR_3064 */
727 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
728 {0x0344, 0x028C}, /* X_ADDR_START */
729 {0x0348, 0x0A0B}, /* X_ADDR_END */
730 {0x0346, 0x006E}, /* Y_ADDR_START */
731 {0x034A, 0x04A5}, /* Y_ADDR_END */
732 {0x034C, 0x0780}, /* X_OUTPUT_SIZE */
733 {0x034E, 0x0438}, /* Y_OUTPUT_SIZE */
734 {0x3040, 0xC041}, /* READ_MODE */
735 {0x306E, 0xFC80}, /* DATAPATH_SELECT */
736 {0x0400, 0x0000}, /* SCALING_MODE */
737 {0x0404, 0x0010}, /* SCALE_M */
738 {0x3178, 0x0000}, /* RESERVED_MFR_3178 */
739 {0x3ED0, 0x1E24}, /* RESERVED_MFR_3ED0 */
740
741 {0x0342, 0x103B}, /* LINE_LENGTH_PCK */
742 {0x0340, 0x05C4}, /* FRAME_LENGTH_LINES */
743 {0x0202, 0x05C4}, /* COARSE_INTEGRATION_TIME */
744 {0x3014, 0x0702}, /* FINE_INTEGRATION_TIME */
745 {0x3010, 0x0078}, /* FINE_CORRECTION */
746 {0x301A, 0x8250}, /* RESET_REGISTER */
747 {0x301A, 0x8650}, /* RESET_REGISTER */
748 {0x301A, 0x8658}, /* RESET_REGISTER */
749 /* gain */
750 {0x305e, 0x10AA}, /* gain */
751 {0x0104, 0x0000}, /* GROUPED_PARAMETER_HOLD */
752 {0x301A, 0x065C}, /* RESET_REGISTER */
753 {ar0832_TABLE_END, 0x0000}
754};
755
756static struct ar0832_reg mode_1920X1080_8141[] = {
757 /* mode start */
758 {0x301A, 0x0058}, /* RESET_REGISTER */
759 {0x301A, 0x0050}, /* RESET_REGISTER */
760 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
761 {0x3064, 0x7800}, /* RESERVED_MFR_3064 */
762 {0x31AE, 0x0202}, /* SERIAL_FORMAT */
763 /* AR0832 Recommended Settings */
764 {0x3044, 0x0590},
765 {0x306E, 0xFC80},
766 {0x30B2, 0xC000},
767 {0x30D6, 0x0800},
768 {0x316C, 0xB42F},
769 {0x316E, 0x869A},
770 {0x3170, 0x210E},
771 {0x317A, 0x010E},
772 {0x31E0, 0x1FB9},
773 {0x31E6, 0x07FC},
774 {0x37C0, 0x0000},
775 {0x37C2, 0x0000},
776 {0x37C4, 0x0000},
777 {0x37C6, 0x0000},
778 {0x3E00, 0x0011},
779 {0x3E02, 0x8801},
780 {0x3E04, 0x2801},
781 {0x3E06, 0x8449},
782 {0x3E08, 0x6841},
783 {0x3E0A, 0x400C},
784 {0x3E0C, 0x1001},
785 {0x3E0E, 0x2603},
786 {0x3E10, 0x4B41},
787 {0x3E12, 0x4B24},
788 {0x3E14, 0xA3CF},
789 {0x3E16, 0x8802},
790 {0x3E18, 0x8401},
791 {0x3E1A, 0x8601},
792 {0x3E1C, 0x8401},
793 {0x3E1E, 0x840A},
794 {0x3E20, 0xFF00},
795 {0x3E22, 0x8401},
796 {0x3E24, 0x00FF},
797 {0x3E26, 0x0088},
798 {0x3E28, 0x2E8A},
799 {0x3E30, 0x0000},
800 {0x3E32, 0x8801},
801 {0x3E34, 0x4029},
802 {0x3E36, 0x00FF},
803 {0x3E38, 0x8469},
804 {0x3E3A, 0x00FF},
805 {0x3E3C, 0x2801},
806 {0x3E3E, 0x3E2A},
807 {0x3E40, 0x1C01},
808 {0x3E42, 0xFF84},
809 {0x3E44, 0x8401},
810 {0x3E46, 0x0C01},
811 {0x3E48, 0x8401},
812 {0x3E4A, 0x00FF},
813 {0x3E4C, 0x8402},
814 {0x3E4E, 0x8984},
815 {0x3E50, 0x6628},
816 {0x3E52, 0x8340},
817 {0x3E54, 0x00FF},
818 {0x3E56, 0x4A42},
819 {0x3E58, 0x2703},
820 {0x3E5A, 0x6752},
821 {0x3E5C, 0x3F2A},
822 {0x3E5E, 0x846A},
823 {0x3E60, 0x4C01},
824 {0x3E62, 0x8401},
825 {0x3E66, 0x3901},
826 {0x3E90, 0x2C01},
827 {0x3E98, 0x2B02},
828 {0x3E92, 0x2A04},
829 {0x3E94, 0x2509},
830 {0x3E96, 0x0000},
831 {0x3E9A, 0x2905},
832 {0x3E9C, 0x00FF},
833 {0x3ECC, 0x00EB},
834 {0x3ED0, 0x1E24},
835 {0x3ED4, 0xAFC4},
836 {0x3ED6, 0x909B},
837 {0x3EE0, 0x2424},
838 {0x3EE2, 0x9797},
839 {0x3EE4, 0xC100},
840 {0x3EE6, 0x0540},
841 {0x3174, 0x8000},
842
843 /* mode end */
844 {0x0300, 0x0004}, /* VT_PIX_CLK_DIV */
845 {0x0302, 0x0001}, /* VT_SYS_CLK_DIV */
846 {0x0304, 0x0002}, /* PRE_PLL_CLK_DIV */
847 {0x0306, 0x0040}, /* PLL_MULTIPLIER */
848 {0x0308, 0x000A}, /* OP_PIX_CLK_DIV */
849 {0x030A, 0x0001}, /* OP_SYS_CLK_DIV */
850 {ar0832_TABLE_WAIT_MS, 0x0001},
851 {0x3064, 0x7400}, /* RESERVED_MFR_3064 */
852 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
853 {0x0344, 0x028C}, /* X_ADDR_START */
854 {0x0348, 0x0A0B}, /* X_ADDR_END */
855 {0x0346, 0x006E}, /* Y_ADDR_START */
856 {0x034A, 0x04A5}, /* Y_ADDR_END */
857 {0x034C, 0x0780}, /* X_OUTPUT_SIZE */
858 {0x034E, 0x0438}, /* Y_OUTPUT_SIZE */
859 {0x3040, 0xC041}, /* READ_MODE */
860 {0x306E, 0xFC80}, /* DATAPATH_SELECT */
861 {0x0400, 0x0000}, /* SCALING_MODE */
862 {0x0404, 0x0010}, /* SCALE_M */
863 {0x3178, 0x0000}, /* RESERVED_MFR_3178 */
864 {0x3ED0, 0x1E24}, /* RESERVED_MFR_3ED0 */
865
866 {0x0342, 0x103B}, /* LINE_LENGTH_PCK */
867 {0x0340, 0x05C4}, /* FRAME_LENGTH_LINES */
868 {0x0202, 0x05C4}, /* COARSE_INTEGRATION_TIME */
869 {0x3014, 0x0702}, /* FINE_INTEGRATION_TIME */
870 {0x3010, 0x0078}, /* FINE_CORRECTION */
871 {0x301A, 0x8250}, /* RESET_REGISTER */
872 {0x301A, 0x8650}, /* RESET_REGISTER */
873 {0x301A, 0x8658}, /* RESET_REGISTER */
874 /* gain */
875 {0x305e, 0x10AA}, /* gain */
876 {0x0104, 0x0000}, /* GROUPED_PARAMETER_HOLD */
877 {0x301A, 0x065C}, /* RESET_REGISTER */
878 {ar0832_TABLE_END, 0x0000}
879};
880
881static struct ar0832_reg mode_1632X1224_8140[] = {
882 /* mode start */
883 {0x301A, 0x0058}, /* RESET_REGISTER */
884 {0x301A, 0x0050}, /* RESET_REGISTER */
885
886 /* SC-CHANGE: to-do 8 bit write */
887 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
888
889 {0x3064, 0x7800}, /* RESERVED_MFR_3064 */
890 {0x31AE, 0x0202}, /* SERIAL_FORMAT */
891 /* MT9E013 Recommended Settings */
892 {0x31B0, 0x0083}, /* FRAME_PREAMBLE */
893 {0x31B2, 0x004D}, /* LINE_PREAMBLE */
894 {0x31B4, 0x0E77}, /* MIPI_TIMING_0 */
895 {0x31B6, 0x0D20}, /* MIPI_TIMING_1 */
896 {0x31B8, 0x020E}, /* MIPI_TIMING_2 */
897 {0x31BA, 0x0710}, /* MIPI_TIMING_3 */
898 {0x31BC, 0x2A0D}, /* MIPI_TIMING_4 */
899 {ar0832_TABLE_WAIT_MS, 0x0005},
900 {0x0112, 0x0A0A}, /* CCP_DATA_FORMAT */
901 {0x3044, 0x0590},
902 {0x306E, 0xFC80},
903 {0x30B2, 0xC000},
904 {0x30D6, 0x0800},
905 {0x316C, 0xB42F},
906 {0x316E, 0x869A},
907 {0x3170, 0x210E},
908 {0x317A, 0x010E},
909 {0x31E0, 0x1FB9},
910 {0x31E6, 0x07FC},
911 {0x37C0, 0x0000},
912 {0x37C2, 0x0000},
913 {0x37C4, 0x0000},
914 {0x37C6, 0x0000},
915 {0x3E00, 0x0011},
916 {0x3E02, 0x8801},
917 {0x3E04, 0x2801},
918 {0x3E06, 0x8449},
919 {0x3E08, 0x6841},
920 {0x3E0A, 0x400C},
921 {0x3E0C, 0x1001},
922 {0x3E0E, 0x2603},
923 {0x3E10, 0x4B41},
924 {0x3E12, 0x4B24},
925 {0x3E14, 0xA3CF},
926 {0x3E16, 0x8802},
927 {0x3E18, 0x8401},
928 {0x3E1A, 0x8601},
929 {0x3E1C, 0x8401},
930 {0x3E1E, 0x840A},
931 {0x3E20, 0xFF00},
932 {0x3E22, 0x8401},
933 {0x3E24, 0x00FF},
934 {0x3E26, 0x0088},
935 {0x3E28, 0x2E8A},
936 {0x3E30, 0x0000},
937 {0x3E32, 0x8801},
938 {0x3E34, 0x4029},
939 {0x3E36, 0x00FF},
940 {0x3E38, 0x8469},
941 {0x3E3A, 0x00FF},
942 {0x3E3C, 0x2801},
943 {0x3E3E, 0x3E2A},
944 {0x3E40, 0x1C01},
945 {0x3E42, 0xFF84},
946 {0x3E44, 0x8401},
947 {0x3E46, 0x0C01},
948 {0x3E48, 0x8401},
949 {0x3E4A, 0x00FF},
950 {0x3E4C, 0x8402},
951 {0x3E4E, 0x8984},
952 {0x3E50, 0x6628},
953 {0x3E52, 0x8340},
954 {0x3E54, 0x00FF},
955 {0x3E56, 0x4A42},
956 {0x3E58, 0x2703},
957 {0x3E5A, 0x6752},
958 {0x3E5C, 0x3F2A},
959 {0x3E5E, 0x846A},
960 {0x3E60, 0x4C01},
961 {0x3E62, 0x8401},
962 {0x3E66, 0x3901},
963 {0x3E90, 0x2C01},
964 {0x3E98, 0x2B02},
965 {0x3E92, 0x2A04},
966 {0x3E94, 0x2509},
967 {0x3E96, 0x0000},
968 {0x3E9A, 0x2905},
969 {0x3E9C, 0x00FF},
970 {0x3ECC, 0x00EB},
971 {0x3ED0, 0x1E24},
972 {0x3ED4, 0xAFC4},
973 {0x3ED6, 0x909B},
974 {0x3EE0, 0x2424},
975 {0x3EE2, 0x9797},
976 {0x3EE4, 0xC100},
977 {0x3EE6, 0x0540},
978 {0x3174, 0x8000},
979
980 /* mode end */
981 {0x0300, 0x0004}, /* VT_PIX_CLK_DIV */
982 {0x0302, 0x0001}, /* VT_SYS_CLK_DIV */
983 {0x0304, 0x0002}, /* PRE_PLL_CLK_DIV */
984
985 {0x0306, 0x0040}, /* PLL_MULTIPLIER */
986
987 {0x0308, 0x000A}, /* OP_PIX_CLK_DIV */
988 {0x030A, 0x0001}, /* OP_SYS_CLK_DIV */
989 {ar0832_TABLE_WAIT_MS, 0x0001}, /* waitmsec 1 */
990
991 {0x3064, 0x7400}, /* RESERVED_MFR_3064 */
992
993 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
994
995 {0x0344, 0x0008}, /* X_ADDR_START */
996 {0x0348, 0x0CC9}, /* X_ADDR_END */
997 {0x0346, 0x0008}, /* Y_ADDR_START */
998 {0x034A, 0x0999}, /* Y_ADDR_END */
999 {0x034C, 0x0660}, /* X_OUTPUT_SIZE */
1000 {0x034E, 0x04C8}, /* Y_OUTPUT_SIZE */
1001 {0x3040, 0xC4C3}, /* READ_MODE */
1002 {0x306E, 0xFC80}, /* DATAPATH_SELECT */
1003 {0x3178, 0x0000}, /* RESERVED_MFR_3178 */
1004 {0x3ED0, 0x1E24}, /* RESERVED_MFR_3ED0 */
1005 {0x0400, 0x0002}, /* SCALING_MODE */
1006 {0x0404, 0x0010}, /* SCALE_M */
1007 {0x0342, 0x101A}, /* LINE_LENGTH_PCK */
1008 {0x0340, 0x0610}, /* FRAME_LENGTH_LINES */
1009 {0x0202, 0x0557}, /* COARSE_INTEGRATION_TIME */
1010 {0x3014, 0x0988}, /* FINE_INTEGRATION_TIME */
1011 {0x3010, 0x0130}, /* FINE_CORRECTION */
1012 {0x301A, 0x8250}, /* RESET_REGISTER */
1013 {0x301A, 0x8650}, /* RESET_REGISTER */
1014 {0x301A, 0x8658}, /* RESET_REGISTER */
1015
1016 /* gain */
1017 {0x305e, 0x10AA}, /* gain */
1018
1019 /* todo 8-bit write */
1020 {0x0104, 0x0000}, /* GROUPED_PARAMETER_HOLD */
1021 {0x301A, 0x065C}, /* RESET_REGISTER */
1022 {ar0832_TABLE_END, 0x0000}
1023};
1024
1025static struct ar0832_reg mode_1632X1224_8141[] = {
1026 /* mode start */
1027 {0x301A, 0x0058}, /* RESET_REGISTER */
1028 {0x301A, 0x0050}, /* RESET_REGISTER */
1029
1030 /* SC-CHANGE: to-do 8 bit write */
1031 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
1032
1033 {0x3064, 0x7800}, /* RESERVED_MFR_3064 */
1034 {0x31AE, 0x0202}, /* SERIAL_FORMAT */
1035 /* AR0832 Recommended Settings */
1036 {0x31B0, 0x0083}, /* FRAME_PREAMBLE */
1037 {0x31B2, 0x004D}, /* LINE_PREAMBLE */
1038 {0x31B4, 0x0E77}, /* MIPI_TIMING_0 */
1039 {0x31B6, 0x0D20}, /* MIPI_TIMING_1 */
1040 {0x31B8, 0x020E}, /* MIPI_TIMING_2 */
1041 {0x31BA, 0x0710}, /* MIPI_TIMING_3 */
1042 {0x31BC, 0x2A0D}, /* MIPI_TIMING_4 */
1043 {ar0832_TABLE_WAIT_MS, 0x0005},
1044 {0x0112, 0x0A0A}, /* CCP_DATA_FORMAT */
1045 {0x3044, 0x0590},
1046 {0x306E, 0xFC80},
1047 {0x30B2, 0xC000},
1048 {0x30D6, 0x0800},
1049 {0x316C, 0xB42F},
1050 {0x316E, 0x869A},
1051 {0x3170, 0x210E},
1052 {0x317A, 0x010E},
1053 {0x31E0, 0x1FB9},
1054 {0x31E6, 0x07FC},
1055 {0x37C0, 0x0000},
1056 {0x37C2, 0x0000},
1057 {0x37C4, 0x0000},
1058 {0x37C6, 0x0000},
1059 {0x3E00, 0x0011},
1060 {0x3E02, 0x8801},
1061 {0x3E04, 0x2801},
1062 {0x3E06, 0x8449},
1063 {0x3E08, 0x6841},
1064 {0x3E0A, 0x400C},
1065 {0x3E0C, 0x1001},
1066 {0x3E0E, 0x2603},
1067 {0x3E10, 0x4B41},
1068 {0x3E12, 0x4B24},
1069 {0x3E14, 0xA3CF},
1070 {0x3E16, 0x8802},
1071 {0x3E18, 0x8401},
1072 {0x3E1A, 0x8601},
1073 {0x3E1C, 0x8401},
1074 {0x3E1E, 0x840A},
1075 {0x3E20, 0xFF00},
1076 {0x3E22, 0x8401},
1077 {0x3E24, 0x00FF},
1078 {0x3E26, 0x0088},
1079 {0x3E28, 0x2E8A},
1080 {0x3E30, 0x0000},
1081 {0x3E32, 0x8801},
1082 {0x3E34, 0x4029},
1083 {0x3E36, 0x00FF},
1084 {0x3E38, 0x8469},
1085 {0x3E3A, 0x00FF},
1086 {0x3E3C, 0x2801},
1087 {0x3E3E, 0x3E2A},
1088 {0x3E40, 0x1C01},
1089 {0x3E42, 0xFF84},
1090 {0x3E44, 0x8401},
1091 {0x3E46, 0x0C01},
1092 {0x3E48, 0x8401},
1093 {0x3E4A, 0x00FF},
1094 {0x3E4C, 0x8402},
1095 {0x3E4E, 0x8984},
1096 {0x3E50, 0x6628},
1097 {0x3E52, 0x8340},
1098 {0x3E54, 0x00FF},
1099 {0x3E56, 0x4A42},
1100 {0x3E58, 0x2703},
1101 {0x3E5A, 0x6752},
1102 {0x3E5C, 0x3F2A},
1103 {0x3E5E, 0x846A},
1104 {0x3E60, 0x4C01},
1105 {0x3E62, 0x8401},
1106 {0x3E66, 0x3901},
1107 {0x3E90, 0x2C01},
1108 {0x3E98, 0x2B02},
1109 {0x3E92, 0x2A04},
1110 {0x3E94, 0x2509},
1111 {0x3E96, 0x0000},
1112 {0x3E9A, 0x2905},
1113 {0x3E9C, 0x00FF},
1114 {0x3ECC, 0x00EB},
1115 {0x3ED0, 0x1E24},
1116 {0x3ED4, 0xAFC4},
1117 {0x3ED6, 0x909B},
1118 {0x3EE0, 0x2424},
1119 {0x3EE2, 0x9797},
1120 {0x3EE4, 0xC100},
1121 {0x3EE6, 0x0540},
1122 {0x3174, 0x8000},
1123
1124 /* mode end */
1125 {0x0300, 0x0004}, /* VT_PIX_CLK_DIV */
1126 {0x0302, 0x0001}, /* VT_SYS_CLK_DIV */
1127 {0x0304, 0x0002}, /* PRE_PLL_CLK_DIV */
1128
1129 {0x0306, 0x0040}, /* PLL_MULTIPLIER */
1130
1131 {0x0308, 0x000A}, /* OP_PIX_CLK_DIV */
1132 {0x030A, 0x0001}, /* OP_SYS_CLK_DIV */
1133 {ar0832_TABLE_WAIT_MS, 0x0001}, /* waitmsec 1 */
1134
1135 {0x3064, 0x7400}, /* RESERVED_MFR_3064 */
1136
1137 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
1138
1139 {0x0344, 0x0008}, /* X_ADDR_START */
1140 {0x0348, 0x0CC9}, /* X_ADDR_END */
1141 {0x0346, 0x0008}, /* Y_ADDR_START */
1142 {0x034A, 0x0999}, /* Y_ADDR_END */
1143 {0x034C, 0x0660}, /* X_OUTPUT_SIZE */
1144 {0x034E, 0x04C8}, /* Y_OUTPUT_SIZE */
1145 {0x3040, 0xC4C3}, /* READ_MODE */
1146 {0x306E, 0xFC80}, /* DATAPATH_SELECT */
1147 {0x3178, 0x0000}, /* RESERVED_MFR_3178 */
1148 {0x3ED0, 0x1E24}, /* RESERVED_MFR_3ED0 */
1149 {0x0400, 0x0002}, /* SCALING_MODE */
1150 {0x0404, 0x0010}, /* SCALE_M */
1151 {0x0342, 0x101A}, /* LINE_LENGTH_PCK */
1152 {0x0340, 0x0610}, /* FRAME_LENGTH_LINES */
1153 {0x0202, 0x0557}, /* COARSE_INTEGRATION_TIME */
1154 {0x3014, 0x0988}, /* FINE_INTEGRATION_TIME */
1155 {0x3010, 0x0130}, /* FINE_CORRECTION */
1156 {0x301A, 0x8250}, /* RESET_REGISTER */
1157 {0x301A, 0x8650}, /* RESET_REGISTER */
1158 {0x301A, 0x8658}, /* RESET_REGISTER */
1159
1160 /* gain */
1161 {0x305e, 0x10AA}, /* gain */
1162
1163 /* todo 8-bit write */
1164 {0x0104, 0x0000}, /* GROUPED_PARAMETER_HOLD */
1165 {0x301A, 0x065C}, /* RESET_REGISTER */
1166 {ar0832_TABLE_END, 0x0000}
1167};
1168
1169static struct ar0832_reg mode_800X600_8140[] = {
1170 /* mode start */
1171 {0x301A, 0x0058},
1172 {0x301A, 0x0050},
1173 {0x0104, 0x0100},
1174 {0x3064, 0x7800},
1175 {0x31AE, 0x0202},
1176 {0x31B8, 0x0E3F},
1177 {0x31BE, 0xC003},
1178 {0x3070, 0x0000},
1179 {ar0832_TABLE_WAIT_MS, 0x0005},
1180
1181 /* MT9E013 Recommended Settings */
1182 {0x3044, 0x0590},
1183 {0x306E, 0xFC80},
1184 {0x30B2, 0xC000},
1185 {0x30D6, 0x0800},
1186 {0x316C, 0xB42F},
1187 {0x316E, 0x869A},
1188 {0x3170, 0x210E},
1189 {0x317A, 0x010E},
1190 {0x31E0, 0x1FB9},
1191 {0x31E6, 0x07FC},
1192 {0x37C0, 0x0000},
1193 {0x37C2, 0x0000},
1194 {0x37C4, 0x0000},
1195 {0x37C6, 0x0000},
1196 {0x3E00, 0x0011},
1197 {0x3E02, 0x8801},
1198 {0x3E04, 0x2801},
1199 {0x3E06, 0x8449},
1200 {0x3E08, 0x6841},
1201 {0x3E0A, 0x400C},
1202 {0x3E0C, 0x1001},
1203 {0x3E0E, 0x2603},
1204 {0x3E10, 0x4B41},
1205 {0x3E12, 0x4B24},
1206 {0x3E14, 0xA3CF},
1207 {0x3E16, 0x8802},
1208 {0x3E18, 0x8401},
1209 {0x3E1A, 0x8601},
1210 {0x3E1C, 0x8401},
1211 {0x3E1E, 0x840A},
1212 {0x3E20, 0xFF00},
1213 {0x3E22, 0x8401},
1214 {0x3E24, 0x00FF},
1215 {0x3E26, 0x0088},
1216 {0x3E28, 0x2E8A},
1217 {0x3E30, 0x0000},
1218 {0x3E32, 0x8801},
1219 {0x3E34, 0x4029},
1220 {0x3E36, 0x00FF},
1221 {0x3E38, 0x8469},
1222 {0x3E3A, 0x00FF},
1223 {0x3E3C, 0x2801},
1224 {0x3E3E, 0x3E2A},
1225 {0x3E40, 0x1C01},
1226 {0x3E42, 0xFF84},
1227 {0x3E44, 0x8401},
1228 {0x3E46, 0x0C01},
1229 {0x3E48, 0x8401},
1230 {0x3E4A, 0x00FF},
1231 {0x3E4C, 0x8402},
1232 {0x3E4E, 0x8984},
1233 {0x3E50, 0x6628},
1234 {0x3E52, 0x8340},
1235 {0x3E54, 0x00FF},
1236 {0x3E56, 0x4A42},
1237 {0x3E58, 0x2703},
1238 {0x3E5A, 0x6752},
1239 {0x3E5C, 0x3F2A},
1240 {0x3E5E, 0x846A},
1241 {0x3E60, 0x4C01},
1242 {0x3E62, 0x8401},
1243 {0x3E66, 0x3901},
1244 {0x3E90, 0x2C01},
1245 {0x3E98, 0x2B02},
1246 {0x3E92, 0x2A04},
1247 {0x3E94, 0x2509},
1248 {0x3E96, 0x0000},
1249 {0x3E9A, 0x2905},
1250 {0x3E9C, 0x00FF},
1251 {0x3ECC, 0x00EB},
1252 {0x3ED0, 0x1E24},
1253 {0x3ED4, 0xAFC4},
1254 {0x3ED6, 0x909B},
1255 {0x3EE0, 0x2424},
1256 {0x3EE2, 0x9797},
1257 {0x3EE4, 0xC100},
1258 {0x3EE6, 0x0540},
1259
1260 /* mode end */
1261 {0x3174, 0x8000},
1262
1263 /* [RAW10] */
1264 {0x0112, 0x0A0A},
1265
1266 /* PLL Configuration Ext=24MHz */
1267 {0x0300, 0x0004},
1268 {0x0302, 0x0001},
1269 {0x0304, 0x0002},
1270 {0x0306, 0x0042},
1271 {0x0308, 0x000A},
1272 {0x030A, 0x0001},
1273 {ar0832_TABLE_WAIT_MS, 0x0001},
1274
1275 /* Output size */
1276 {0x0344, 0x04D8},
1277 {0x0348, 0x07F7},
1278 {0x0346, 0x03A4},
1279 {0x034A, 0x05FB},
1280 {0x034C, 0x0320},
1281 {0x034E, 0x0258},
1282 {0x3040, 0xC041},
1283
1284 {0x306E, 0xFC80},
1285 {0x3178, 0x0000},
1286 {0x3ED0, 0x1E24},
1287
1288 /* Scale Configuration */
1289 {0x0400, 0x0000},
1290 {0x0404, 0x0010},
1291
1292 /* Timing Configuration */
1293 {0x0342, 0x08A8},
1294 {0x0340, 0x02E7},
1295 {0x0202, 0x02E7},
1296 {0x3014, 0x03F6},
1297 {0x3010, 0x0078},
1298
1299 {0x301A, 0x8250},
1300 {0x301A, 0x8650},
1301 {0x301A, 0x8658},
1302 /* STATE= Minimum Gain, 1500 */
1303 {0x305E, 0x13AF},
1304
1305 {0x0104, 0x0000},
1306 {0x301A, 0x065C},
1307 {ar0832_TABLE_END, 0x0000}
1308};
1309
1310static struct ar0832_reg mode_800X600_8141[] = {
1311 /* mode start */
1312 {0x301A, 0x0058}, /* RESET_REGISTER */
1313 {0x301A, 0x0050}, /* RESET_REGISTER */
1314
1315 /* SC-CHANGE: to-do 8 bit write */
1316 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
1317
1318 {0x3064, 0x7800}, /* RESERVED_MFR_3064 */
1319 {0x31AE, 0x0202}, /* SERIAL_FORMAT */
1320 /* AR0832 Recommended Settings */
1321 {0x31B0, 0x0083}, /* FRAME_PREAMBLE */
1322 {0x31B2, 0x004D}, /* LINE_PREAMBLE */
1323 {0x31B4, 0x0E88}, /* MIPI_TIMING_0 */
1324 {0x31B6, 0x0D24}, /* MIPI_TIMING_1 */
1325 {0x31B8, 0x020E}, /* MIPI_TIMING_2 */
1326 {0x31BA, 0x0710}, /* MIPI_TIMING_3 */
1327 {0x31BC, 0x2A0D}, /* MIPI_TIMING_4 */
1328 {ar0832_TABLE_WAIT_MS, 0x0005},
1329 {0x0112, 0x0A0A}, /* CCP_DATA_FORMAT */
1330 {0x3044, 0x0590}, /* RESERVED_MFR_3044 */
1331 {0x306E, 0xFC80}, /* DATAPATH_SELECT */
1332 {0x30B2, 0xC000}, /* RESERVED_MFR_30B2 */
1333 {0x30D6, 0x0800}, /* RESERVED_MFR_30D6 */
1334 {0x316C, 0xB42F}, /* RESERVED_MFR_316C */
1335 {0x316E, 0x869A}, /* RESERVED_MFR_316E */
1336 {0x3170, 0x210E}, /* RESERVED_MFR_3170 */
1337 {0x317A, 0x010E}, /* RESERVED_MFR_317A */
1338 {0x31E0, 0x1FB9}, /* RESERVED_MFR_31E0 */
1339 {0x31E6, 0x07FC}, /* RESERVED_MFR_31E6 */
1340 {0x37C0, 0x0000}, /* P_GR_Q5 */
1341 {0x37C2, 0x0000}, /* P_RD_Q5 */
1342 {0x37C4, 0x0000}, /* P_BL_Q5 */
1343 {0x37C6, 0x0000}, /* P_GB_Q5 */
1344 {0x3E00, 0x0011}, /* RESERVED_MFR_3E00 */
1345 {0x3E02, 0x8801}, /* RESERVED_MFR_3E02 */
1346 {0x3E04, 0x2801}, /* RESERVED_MFR_3E04 */
1347 {0x3E06, 0x8449}, /* RESERVED_MFR_3E06 */
1348 {0x3E08, 0x6841}, /* RESERVED_MFR_3E08 */
1349 {0x3E0A, 0x400C}, /* RESERVED_MFR_3E0A */
1350 {0x3E0C, 0x1001}, /* RESERVED_MFR_3E0C */
1351 {0x3E0E, 0x2603}, /* RESERVED_MFR_3E0E */
1352 {0x3E10, 0x4B41}, /* RESERVED_MFR_3E10 */
1353 {0x3E12, 0x4B24}, /* RESERVED_MFR_3E12 */
1354 {0x3E14, 0xA3CF}, /* RESERVED_MFR_3E14 */
1355 {0x3E16, 0x8802}, /* RESERVED_MFR_3E16 */
1356 {0x3E18, 0x84FF}, /* RESERVED_MFR_3E18 */
1357 {0x3E1A, 0x8601}, /* RESERVED_MFR_3E1A */
1358 {0x3E1C, 0x8401}, /* RESERVED_MFR_3E1C */
1359 {0x3E1E, 0x840A}, /* RESERVED_MFR_3E1E */
1360 {0x3E20, 0xFF00}, /* RESERVED_MFR_3E20 */
1361 {0x3E22, 0x8401}, /* RESERVED_MFR_3E22 */
1362 {0x3E24, 0x00FF}, /* RESERVED_MFR_3E24 */
1363 {0x3E26, 0x0088}, /* RESERVED_MFR_3E26 */
1364 {0x3E28, 0x2E8A}, /* RESERVED_MFR_3E28 */
1365 {0x3E30, 0x0000}, /* RESERVED_MFR_3E30 */
1366 {0x3E32, 0x8801}, /* RESERVED_MFR_3E32 */
1367 {0x3E34, 0x4029}, /* RESERVED_MFR_3E34 */
1368 {0x3E36, 0x00FF}, /* RESERVED_MFR_3E36 */
1369 {0x3E38, 0x8469}, /* RESERVED_MFR_3E38 */
1370 {0x3E3A, 0x00FF}, /* RESERVED_MFR_3E3A */
1371 {0x3E3C, 0x2801}, /* RESERVED_MFR_3E3C */
1372 {0x3E3E, 0x3E2A}, /* RESERVED_MFR_3E3E */
1373 {0x3E40, 0x1C01}, /* RESERVED_MFR_3E40 */
1374 {0x3E42, 0xFF84}, /* RESERVED_MFR_3E42 */
1375 {0x3E44, 0x8401}, /* RESERVED_MFR_3E44 */
1376 {0x3E46, 0x0C01}, /* RESERVED_MFR_3E46 */
1377 {0x3E48, 0x8401}, /* RESERVED_MFR_3E48 */
1378 {0x3E4A, 0x00FF}, /* RESERVED_MFR_3E4A */
1379 {0x3E4C, 0x8402}, /* RESERVED_MFR_3E4C */
1380 {0x3E4E, 0x8984}, /* RESERVED_MFR_3E4E */
1381 {0x3E50, 0x6628}, /* RESERVED_MFR_3E50 */
1382 {0x3E52, 0x8340}, /* RESERVED_MFR_3E52 */
1383 {0x3E54, 0x00FF}, /* RESERVED_MFR_3E54 */
1384 {0x3E56, 0x4A42}, /* RESERVED_MFR_3E56 */
1385 {0x3E58, 0x2703}, /* RESERVED_MFR_3E58 */
1386 {0x3E5A, 0x6752}, /* RESERVED_MFR_3E5A */
1387 {0x3E5C, 0x3F2A}, /* RESERVED_MFR_3E5C */
1388 {0x3E5E, 0x846A}, /* RESERVED_MFR_3E5E */
1389 {0x3E60, 0x4C01}, /* RESERVED_MFR_3E60 */
1390 {0x3E62, 0x8401}, /* RESERVED_MFR_3E62 */
1391 {0x3E66, 0x3901}, /* RESERVED_MFR_3E66 */
1392 {0x3E90, 0x2C01}, /* RESERVED_MFR_3E90 */
1393 {0x3E98, 0x2B02}, /* RESERVED_MFR_3E98 */
1394 {0x3E92, 0x2A04}, /* RESERVED_MFR_3E92 */
1395 {0x3E94, 0x2509}, /* RESERVED_MFR_3E94 */
1396 {0x3E96, 0x0000}, /* RESERVED_MFR_3E96 */
1397 {0x3E9A, 0x2905}, /* RESERVED_MFR_3E9A */
1398 {0x3E9C, 0x00FF}, /* RESERVED_MFR_3E9C */
1399 {0x3ECC, 0x00EB}, /* RESERVED_MFR_3ECC */
1400 {0x3ED0, 0x1E24}, /* RESERVED_MFR_3ED0 */
1401 {0x3ED4, 0xAFC4}, /* RESERVED_MFR_3ED4 */
1402 {0x3ED6, 0x909B}, /* RESERVED_MFR_3ED6 */
1403 {0x3EE0, 0x2424}, /* RESERVED_MFR_3EE0 */
1404 {0x3EE2, 0x9797}, /* RESERVED_MFR_3EE2 */
1405 {0x3EE4, 0xC100}, /* RESERVED_MFR_3EE4 */
1406 {0x3EE6, 0x0540}, /* RESERVED_MFR_3EE6 */
1407
1408 /* mode end */
1409 {0x3174, 0x8000}, /* RESERVED_MFR_3174 */
1410 {0x0300, 0x0004}, /* VT_PIX_CLK_DIV */
1411 {0x0302, 0x0001}, /* VT_SYS_CLK_DIV */
1412 {0x0304, 0x0002}, /* PRE_PLL_CLK_DIV */
1413
1414 {0x0306, 0x0042}, /* PLL_MULTIPLIER */
1415
1416 {0x0308, 0x000A}, /* OP_PIX_CLK_DIV */
1417 {0x030A, 0x0001}, /* OP_SYS_CLK_DIV */
1418 {ar0832_TABLE_WAIT_MS, 0x0001}, /* waitmsec 1 */
1419
1420 {0x3064, 0x7400}, /* RESERVED_MFR_3064 */
1421
1422 {0x0104, 0x0100}, /* GROUPED_PARAMETER_HOLD */
1423
1424 {0x0344, 0x04D8}, /* X_ADDR_START */
1425 {0x0348, 0x07F7}, /* X_ADDR_END */
1426 {0x0346, 0x03A4}, /* Y_ADDR_START */
1427 {0x034A, 0x05FB}, /* Y_ADDR_END */
1428 {0x034C, 0x0320}, /* X_OUTPUT_SIZE */
1429 {0x034E, 0x0260}, /* Y_OUTPUT_SIZE */
1430 {0x3040, 0xC041}, /* READ_MODE */
1431 {0x306E, 0xFC80}, /* DATAPATH_SELECT */
1432 {0x3178, 0x0000}, /* RESERVED_MFR_3178 */
1433 {0x3ED0, 0x1E24}, /* RESERVED_MFR_3ED0 */
1434 {0x0400, 0x0000}, /* SCALING_MODE */
1435 {0x0404, 0x0010}, /* SCALE_M */
1436 {0x0342, 0x08A8}, /* LINE_LENGTH_PCK */
1437 {0x0340, 0x02E7}, /* FRAME_LENGTH_LINES */
1438 {0x0202, 0x02E7}, /* COARSE_INTEGRATION_TIME */
1439 {0x3014, 0x03F6}, /* FINE_INTEGRATION_TIME */
1440 {0x3010, 0x0078}, /* FINE_CORRECTION */
1441 {0x301A, 0x8250}, /* RESET_REGISTER */
1442 {0x301A, 0x8650}, /* RESET_REGISTER */
1443 {0x301A, 0x8658}, /* RESET_REGISTER */
1444
1445 /* gain */
1446 {0x305e, 0x10AA}, /* gain */
1447
1448 /* todo 8-bit write */
1449 {0x0104, 0x0000}, /* GROUPED_PARAMETER_HOLD */
1450 {0x301A, 0x065C}, /* RESET_REGISTER */
1451 {ar0832_TABLE_END, 0x0000}
1452};
1453
1454static struct ar0832_reg mode_end[] = {
1455 {ar0832_TABLE_END, 0x0000}
1456};
1457
1458enum {
1459 ar0832_MODE_3264X2448,
1460 ar0832_MODE_2880X1620,
1461 ar0832_MODE_1920X1080,
1462 ar0832_MODE_1632X1224,
1463 ar0832_MODE_800X600
1464};
1465
1466static struct ar0832_reg *mode_table_8140[] = {
1467 [ar0832_MODE_3264X2448] = mode_3264X2448_8140,
1468 [ar0832_MODE_2880X1620] = mode_2880X1620_8140,
1469 [ar0832_MODE_1920X1080] = mode_1920X1080_8140,
1470 [ar0832_MODE_1632X1224] = mode_1632X1224_8140,
1471 [ar0832_MODE_800X600] = mode_800X600_8140,
1472};
1473
1474static struct ar0832_reg *mode_table_8141[] = {
1475 [ar0832_MODE_3264X2448] = mode_3264X2448_8141,
1476 [ar0832_MODE_2880X1620] = mode_2880X1620_8141,
1477 [ar0832_MODE_1920X1080] = mode_1920X1080_8141,
1478 [ar0832_MODE_1632X1224] = mode_1632X1224_8141,
1479 [ar0832_MODE_800X600] = mode_800X600_8141,
1480};
1481
1482static inline void ar0832_msleep(u32 t)
1483{
1484 /*
1485 why usleep_range() instead of msleep() ?
1486 Read Documentation/timers/timers-howto.txt
1487 */
1488 usleep_range(t*1000, t*1000 + 500);
1489}
1490
1491/* 16 bit reg to program frame length */
1492static inline void ar0832_get_frame_length_regs(struct ar0832_reg *regs,
1493 u32 frame_length)
1494{
1495 regs->addr = 0x0340;
1496 regs->val = (frame_length) & 0xFFFF;
1497}
1498
1499static inline void ar0832_get_coarse_time_regs(struct ar0832_reg *regs,
1500 u32 coarse_time)
1501{
1502 regs->addr = 0x0202;
1503 regs->val = (coarse_time) & 0xFFFF;
1504}
1505
1506static inline void ar0832_get_focuser_vcm_control_regs(struct ar0832_reg *regs,
1507 u16 value)
1508{
1509 regs->addr = 0x30F0;
1510 regs->val = (value) & 0xFFFF;
1511}
1512
1513static inline void ar0832_get_focuser_vcm_step_time_regs
1514 (struct ar0832_reg *regs, u16 value)
1515{
1516 regs->addr = 0x30F4;
1517 regs->val = (value) & 0xFFFF;
1518}
1519
1520static inline void ar0832_get_focuser_data_regs(struct ar0832_reg *regs,
1521 u16 value)
1522{
1523 regs->addr = 0x30F2;
1524 regs->val = (value) & 0xFFFF;
1525}
1526
1527static inline void ar0832_get_gain_regs(struct ar0832_reg *regs, u16 gain)
1528{
1529 /* global_gain register*/
1530 regs->addr = AR0832_GLOBAL_GAIN_REG;
1531 regs->val = gain;
1532}
1533
1534static int ar0832_write_reg8(struct i2c_client *client, u16 addr, u8 val)
1535{
1536 int err;
1537 struct i2c_msg msg;
1538 unsigned char data[3];
1539 int retry = 0;
1540
1541 if (!client->adapter)
1542 return -ENODEV;
1543
1544 data[0] = (u8) (addr >> 8);;
1545 data[1] = (u8) (addr & 0xff);
1546 data[2] = (u8) (val & 0xff);
1547
1548 msg.addr = client->addr;
1549 msg.flags = 0;
1550 msg.len = 3;
1551 msg.buf = data;
1552
1553 dev_dbg(&client->dev, "0x%x = 0x%x\n", addr, val);
1554
1555 do {
1556 err = i2c_transfer(client->adapter, &msg, 1);
1557 if (err > 0)
1558 return 0;
1559 retry++;
1560 dev_err(&client->dev,
1561 "%s: i2c transfer failed, retrying %x %x\n",
1562 __func__, addr, val);
1563 ar0832_msleep(3);
1564 } while (retry < ar0832_MAX_RETRIES);
1565
1566 return err;
1567}
1568
1569static int ar0832_write_reg16(struct i2c_client *client, u16 addr, u16 val)
1570{
1571 int count;
1572 struct i2c_msg msg;
1573 unsigned char data[4];
1574 int retry = 0;
1575
1576 if (!client->adapter)
1577 return -ENODEV;
1578
1579 data[0] = (u8) (addr >> 8);
1580 data[1] = (u8) (addr & 0xff);
1581 data[2] = (u8) (val >> 8);
1582 data[3] = (u8) (val & 0xff);
1583
1584 msg.addr = client->addr;
1585 msg.flags = 0;
1586 msg.len = 4;
1587 msg.buf = data;
1588
1589 dev_dbg(&client->dev, "0x%x = 0x%x\n", addr, val);
1590
1591 do {
1592 count = i2c_transfer(client->adapter, &msg, 1);
1593 if (count == 1)
1594 return 0;
1595 retry++;
1596 dev_err(&client->dev,
1597 "%s: i2c transfer failed, retrying %x %x\n",
1598 __func__, addr, val);
1599 ar0832_msleep(3);
1600 } while (retry <= ar0832_MAX_RETRIES);
1601
1602 return -EIO;
1603}
1604
1605static int ar0832_read_reg16(struct i2c_client *client, u16 addr, u16 *val)
1606{
1607 struct i2c_msg msg[2];
1608 u8 data[4];
1609
1610 msg[0].addr = client->addr;
1611 msg[0].flags = 0;
1612 msg[0].len = 2;
1613 msg[0].buf = data;
1614 data[0] = (addr >> 8);
1615 data[1] = (addr & 0xff);
1616 msg[1].addr = client->addr;
1617 msg[1].flags = I2C_M_RD;
1618 msg[1].len = 2;
1619 msg[1].buf = data + 2;
1620
1621 if (i2c_transfer(client->adapter, msg, 2) == 2) {
1622 *val = ((data[2] << 8) | data[3]);
1623 dev_dbg(&client->dev, "0x%x = 0x%x\n", addr, *val);
1624 return 0;
1625 } else {
1626 *val = 0;
1627 dev_err(&client->dev,
1628 "%s: i2c read failed.\n", __func__);
1629 return -1;
1630 }
1631}
1632
1633static int ar0832_write_reg_helper(struct ar0832_dev *dev,
1634 u16 addr,
1635 u16 val)
1636{
1637 int ret;
1638
1639 if (addr == 0x104)
1640 ret = ar0832_write_reg8(dev->i2c_client, addr,
1641 (val >> 8 & 0xff));
1642 else
1643 ret = ar0832_write_reg16(dev->i2c_client, addr, val);
1644
1645 return ret;
1646}
1647
1648static int ar0832_write_table(struct ar0832_dev *dev,
1649 const struct ar0832_reg table[],
1650 const struct ar0832_reg override_list[],
1651 int num_override_regs)
1652{
1653 int err;
1654 const struct ar0832_reg *next;
1655 u16 val;
1656 int i;
1657
1658 for (next = table; next->addr != ar0832_TABLE_END; next++) {
1659 if (next->addr == ar0832_TABLE_WAIT_MS) {
1660 ar0832_msleep(next->val);
1661 continue;
1662 }
1663
1664 val = next->val;
1665 /* When an override list is passed in, replace the reg */
1666 /* value to write if the reg is in the list */
1667 if (override_list) {
1668 for (i = 0; i < num_override_regs; i++) {
1669 if (next->addr == override_list[i].addr) {
1670 val = override_list[i].val;
1671 break;
1672 }
1673 }
1674 }
1675
1676 err = ar0832_write_reg_helper(dev, next->addr, val);
1677 if (err)
1678 return err;
1679 }
1680 return 0;
1681}
1682
1683static int ar0832_set_frame_length(struct ar0832_dev *dev,
1684 u32 frame_length)
1685{
1686 struct ar0832_reg reg_list;
1687 struct i2c_client *i2c_client = dev->i2c_client;
1688 int ret;
1689
1690 dev_dbg(&i2c_client->dev, "[%s] (0x%08x)\n", __func__, frame_length);
1691
1692 ar0832_get_frame_length_regs(&reg_list, frame_length);
1693 ret = ar0832_write_reg8(i2c_client, AR0832_GROUP_HOLD_REG, 0x1);
1694 if (ret)
1695 return ret;
1696
1697 ret = ar0832_write_reg16(i2c_client, reg_list.addr,
1698 reg_list.val);
1699 if (ret)
1700 return ret;
1701
1702 ret = ar0832_write_reg8(i2c_client, AR0832_GROUP_HOLD_REG, 0x0);
1703 if (ret)
1704 return ret;
1705
1706 return 0;
1707}
1708
1709static int ar0832_set_coarse_time(struct ar0832_dev *dev,
1710 u32 coarse_time)
1711{
1712 int ret;
1713 struct ar0832_reg reg_list;
1714 struct i2c_client *i2c_client = dev->i2c_client;
1715
1716 dev_dbg(&i2c_client->dev, "[%s] (0x%08x)\n", __func__, coarse_time);
1717 ar0832_get_coarse_time_regs(&reg_list, coarse_time);
1718
1719 ret = ar0832_write_reg8(i2c_client, AR0832_GROUP_HOLD_REG, 0x1);
1720 if (ret)
1721 return ret;
1722
1723 ret = ar0832_write_reg16(i2c_client, reg_list.addr,
1724 reg_list.val);
1725 if (ret)
1726 return ret;
1727
1728 ret = ar0832_write_reg8(i2c_client, AR0832_GROUP_HOLD_REG, 0x0);
1729 if (ret)
1730 return ret;
1731
1732 return 0;
1733}
1734
1735static int ar0832_set_gain(struct ar0832_dev *dev, u16 gain)
1736{
1737 int ret = 0;
1738 struct ar0832_reg reg_list_gain;
1739
1740 ret = ar0832_write_reg8(dev->i2c_client, AR0832_GROUP_HOLD_REG, 0x1);
1741 /* Gain Registers Start */
1742 ar0832_get_gain_regs(&reg_list_gain, gain);
1743 ret |= ar0832_write_reg16(dev->i2c_client,
1744 reg_list_gain.addr,
1745 reg_list_gain.val);
1746 if (ret)
1747 return ret;
1748
1749 /* Gain register End */
1750 ret |= ar0832_write_reg8(dev->i2c_client, AR0832_GROUP_HOLD_REG, 0x0);
1751
1752 return ret;
1753}
1754
1755static int ar0832_set_mode(struct ar0832_dev *dev,
1756 struct ar0832_mode *mode)
1757{
1758 int sensor_mode;
1759 int err;
1760 struct i2c_client *i2c_client = dev->i2c_client;
1761 struct ar0832_reg reg_ovr[3];
1762 struct ar0832_reg *mode_seq;
1763
1764 dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
1765
1766 if (mode->xres == 3264 && mode->yres == 2448)
1767 sensor_mode = ar0832_MODE_3264X2448;
1768 else if (mode->xres == 2880 && mode->yres == 1620)
1769 sensor_mode = ar0832_MODE_2880X1620;
1770 else if (mode->xres == 1920 && mode->yres == 1080)
1771 sensor_mode = ar0832_MODE_1920X1080;
1772 else if (mode->xres == 1632 && mode->yres == 1224)
1773 sensor_mode = ar0832_MODE_1632X1224;
1774 else if (mode->xres == 800 && mode->yres == 600)
1775 sensor_mode = ar0832_MODE_800X600;
1776 else {
1777 dev_err(&i2c_client->dev,
1778 "%s: invalid resolution supplied to set mode %d %d\n",
1779 __func__ , mode->xres, mode->yres);
1780 return -EINVAL;
1781 }
1782
1783 if (dev->sensor_id_data == AR0832_SENSOR_ID_8141)
1784 mode_seq = mode_table_8141[sensor_mode];
1785 else
1786 mode_seq = mode_table_8140[sensor_mode];
1787 /* get a list of override regs for the asking frame length, */
1788 /* coarse integration time, and gain.*/
1789 err = ar0832_write_table(dev, mode_start, NULL, 0);
1790 if (err)
1791 return err;
1792
1793 /* When we change the resolution */
1794 ar0832_get_frame_length_regs(&reg_ovr[0], mode->frame_length);
1795 ar0832_get_coarse_time_regs(&reg_ovr[1], mode->coarse_time);
1796 ar0832_get_gain_regs(&reg_ovr[2], mode->gain);
1797 err = ar0832_write_table(dev, mode_seq, reg_ovr, ARRAY_SIZE(reg_ovr));
1798 if (err)
1799 return err;
1800
1801 err = ar0832_write_table(dev, mode_end, NULL, 0);
1802 if (err)
1803 return err;
1804
1805 dev->sensor_info->mode = sensor_mode;
1806 dev_dbg(&i2c_client->dev, "%s: --\n", __func__);
1807
1808 return 0;
1809}
1810
1811static int ar0832_get_status(struct ar0832_dev *dev, u8 *status)
1812{
1813 int err = 0;
1814 struct i2c_client *i2c_client = dev->i2c_client;
1815
1816 *status = 0;
1817 /* FixMe */
1818 /*
1819 err = ar0832_read_reg(dev->i2c_client, 0x001, status);
1820 */
1821 dev_dbg(&i2c_client->dev, "%s: %u %d\n", __func__, *status, err);
1822 return err;
1823}
1824
1825static int ar0832_set_alternate_addr(struct i2c_client *client)
1826{
1827 int ret = 0;
1828 u8 new_addr = client->addr;
1829 u16 val;
1830
1831 /* Default slave address of ar0832 is 0x36 */
1832 client->addr = 0x36;
1833 ret = ar0832_read_reg16(client, AR0832_RESET_REG, &val);
1834 val &= ~AR0832_RESET_REG_LOCK_REG;
1835 ret |= ar0832_write_reg16(client, AR0832_RESET_REG, val);
1836 ret |= ar0832_write_reg16(client, AR0832_ID_REG, new_addr << 1);
1837
1838 if (!ret) {
1839 client->addr = new_addr;
1840 dev_dbg(&client->dev,
1841 "new slave address is set to 0x%x\n", new_addr);
1842 }
1843
1844 ret |= ar0832_read_reg16(client, AR0832_RESET_REG, &val);
1845 val |= AR0832_RESET_REG_LOCK_REG;
1846 ret |= ar0832_write_reg16(client, AR0832_RESET_REG, val);
1847
1848 return ret;
1849}
1850
1851static int ar0832_power_on(struct ar0832_dev *dev)
1852{
1853 struct i2c_client *i2c_client = dev->i2c_client;
1854 int ret = 0;
1855
1856 dev_dbg(&i2c_client->dev, "%s: ++ %d %d\n",
1857 __func__, dev->is_stereo,
1858 dev->brd_power_cnt);
1859
1860 /* Board specific power-on sequence */
1861 mutex_lock(&dev->ar0832_camera_lock);
1862 if (dev->brd_power_cnt == 0) {
1863 /* Plug 1.8V and 2.8V power to sensor */
1864 if (dev->power_rail.sen_1v8_reg) {
1865 ret = regulator_enable(dev->power_rail.sen_1v8_reg);
1866 if (ret) {
1867 dev_err(&i2c_client->dev,
1868 "%s: failed to enable vdd\n",
1869 __func__);
1870 goto fail_regulator_1v8_reg;
1871 }
1872 }
1873
1874 if (dev->power_rail.sen_2v8_reg) {
1875 ret = regulator_enable(dev->power_rail.sen_2v8_reg);
1876 if (ret) {
1877 dev_err(&i2c_client->dev,
1878 "%s: failed to enable vaa\n",
1879 __func__);
1880 goto fail_regulator_2v8_reg;
1881 }
1882 }
1883 dev->pdata->power_on(dev->is_stereo);
1884 }
1885 dev->brd_power_cnt++;
1886 mutex_unlock(&dev->ar0832_camera_lock);
1887
1888 /* Change slave address */
1889 if (i2c_client->addr)
1890 ret = ar0832_set_alternate_addr(i2c_client);
1891
1892 return 0;
1893
1894fail_regulator_2v8_reg:
1895 regulator_put(dev->power_rail.sen_2v8_reg);
1896 dev->power_rail.sen_2v8_reg = NULL;
1897 regulator_disable(dev->power_rail.sen_1v8_reg);
1898fail_regulator_1v8_reg:
1899 regulator_put(dev->power_rail.sen_1v8_reg);
1900 dev->power_rail.sen_1v8_reg = NULL;
1901 return ret;
1902}
1903
1904static void ar0832_power_off(struct ar0832_dev *dev)
1905{
1906 struct i2c_client *i2c_client = dev->i2c_client;
1907 dev_dbg(&i2c_client->dev, "%s: ++ %d\n", __func__, dev->brd_power_cnt);
1908
1909 /* Board specific power-down sequence */
1910 mutex_lock(&dev->ar0832_camera_lock);
1911
1912 if (dev->brd_power_cnt <= 0)
1913 goto ar0832_pwdn_exit;
1914
1915 if (dev->brd_power_cnt-- == 1) {
1916 /* Unplug 1.8V and 2.8V power from sensor */
1917 if (dev->power_rail.sen_2v8_reg)
1918 regulator_disable(dev->power_rail.sen_2v8_reg);
1919 if (dev->power_rail.sen_1v8_reg)
1920 regulator_disable(dev->power_rail.sen_1v8_reg);
1921 dev->pdata->power_off(dev->is_stereo);
1922 }
1923
1924ar0832_pwdn_exit:
1925 mutex_unlock(&dev->ar0832_camera_lock);
1926}
1927
1928static int ar0832_focuser_set_config(struct ar0832_dev *dev)
1929{
1930 struct i2c_client *i2c_client = dev->i2c_client;
1931 struct ar0832_reg reg_vcm_ctrl, reg_vcm_step_time;
1932 int ret = 0;
1933 u8 vcm_slew = 1;
1934
1935 /* bit15(0x80) means that VCM driver enable bit. */
1936 /* bit3(0x08) means that keep VCM(AF position) */
1937 /* while sensor is in soft standby mode during mode transitions. */
1938 u16 vcm_control_data = (0x80 << 8 | (0x08 | (vcm_slew & 0x07)));
1939 u16 vcm_step_time = 1024;
1940
1941 ar0832_get_focuser_vcm_control_regs(&reg_vcm_ctrl, vcm_control_data);
1942 ret = ar0832_write_reg16(dev->i2c_client, reg_vcm_ctrl.addr,
1943 reg_vcm_ctrl.val);
1944
1945 dev_dbg(&i2c_client->dev, "%s Reg 0x%X Value 0x%X\n", __func__,
1946 reg_vcm_ctrl.addr, reg_vcm_ctrl.val);
1947
1948 if (ret) {
1949 dev_dbg(&i2c_client->dev, "%s Error writing to register 0x%X\n",
1950 __func__, reg_vcm_ctrl.addr);
1951 return ret;
1952 }
1953
1954 ar0832_get_focuser_vcm_step_time_regs(&reg_vcm_step_time,
1955 vcm_step_time);
1956 ret = ar0832_write_reg16(dev->i2c_client, reg_vcm_step_time.addr,
1957 reg_vcm_step_time.val);
1958
1959 dev_dbg(&i2c_client->dev, "%s Reg step_time 0x%X Value 0x%X\n",
1960 __func__, reg_vcm_step_time.addr,
1961 reg_vcm_step_time.val);
1962
1963 return ret;
1964}
1965
1966static int ar0832_focuser_set_position(struct ar0832_dev *dev,
1967 u32 position)
1968{
1969 int ret = 0;
1970 struct ar0832_reg reg_data;
1971
1972 ar0832_get_focuser_data_regs(&reg_data, position);
1973 ret = ar0832_write_reg16(dev->i2c_client, reg_data.addr,
1974 reg_data.val);
1975 dev->focuser_info->last_position = position;
1976
1977 return ret;
1978}
1979
1980
1981/*
1982 * This function is not currently called as we have the hardcoded
1983 * step time in ar0832_focuser_set_config function. If we need to
1984 * compute the actual step time based on a number of clocks, we need
1985 * to use this function. The formula for computing the clock-based
1986 * step time is obtained from Aptina and is not part of external
1987 * documentation and hence this code needs to be saved.
1988 */
1989static u16 ar0832_get_focuser_vcm_step_time(struct ar0832_dev *dev)
1990{
1991 struct i2c_client *i2c_client = dev->i2c_client;
1992 int ret;
1993 u16 pll_multiplier = 0;
1994 u16 pre_pll_clk_div = 0;
1995 u16 vt_sys_clk_div = 0;
1996 u16 vt_pix_clk_div = 0;
1997 u16 vt_pix_clk_freq_mhz = 0;
1998
1999 ret = ar0832_read_reg16(dev->i2c_client, 0x306, &pll_multiplier);
2000 if (ret) {
2001 dev_err(&i2c_client->dev, "%s pll_multiplier read failed\n",
2002 __func__);
2003 }
2004
2005 ret = ar0832_read_reg16(dev->i2c_client, 0x304, &pre_pll_clk_div);
2006 if (ret) {
2007 dev_err(&i2c_client->dev, "%s pre_pll_clk_div read failed\n",
2008 __func__);
2009 }
2010
2011 ret = ar0832_read_reg16(dev->i2c_client, 0x302, &vt_sys_clk_div);
2012 if (ret) {
2013 dev_err(&i2c_client->dev, "%s vt_sys_clk_div read failed\n",
2014 __func__);
2015 }
2016
2017 ret = ar0832_read_reg16(dev->i2c_client, 0x300, &vt_pix_clk_div);
2018 if (ret) {
2019 dev_err(&i2c_client->dev, "%s vt_pix_clk_div read failed\n",
2020 __func__);
2021 }
2022
2023 vt_pix_clk_freq_mhz =
2024 (24 * pll_multiplier) / (pre_pll_clk_div * vt_sys_clk_div *
2025 vt_pix_clk_div);
2026
2027 dev_dbg(&i2c_client->dev, "%s pll_multiplier 0x%X pre_pll_clk_div 0x%X "
2028 "vt_sys_clk_div 0x%X vt_pix_clk_div 0x%X vt_pix_clk_freq_mhz 0x%X\n",
2029 __func__, pll_multiplier,
2030 pre_pll_clk_div, vt_sys_clk_div,
2031 vt_pix_clk_div, vt_pix_clk_freq_mhz);
2032
2033 return vt_pix_clk_freq_mhz;
2034
2035}
2036
2037static inline
2038int ar0832_get_sensorid(struct ar0832_dev *dev, u16 *sensor_id)
2039{
2040 int ret;
2041 struct i2c_client *i2c_client = dev->i2c_client;
2042
2043 ret = ar0832_power_on(dev);
2044 if (ret)
2045 return ret;
2046
2047 ret = ar0832_read_reg16(i2c_client, AR0832_SENSORID_REG, sensor_id);
2048 dev_dbg(&i2c_client->dev,
2049 "%s: sensor_id - %04x\n", __func__, *sensor_id);
2050
2051 ar0832_power_off(dev);
2052
2053 return ret;
2054}
2055
2056static long ar0832_ioctl(struct file *file,
2057 unsigned int cmd, unsigned long arg)
2058{
2059 int err;
2060 struct ar0832_dev *dev = file->private_data;
2061 struct i2c_client *i2c_client = dev->i2c_client;
2062 struct ar0832_mode mode;
2063 u16 pos;
2064
2065 switch (cmd) {
2066 case AR0832_IOCTL_SET_POWER_ON:
2067 dev_dbg(&i2c_client->dev, "AR0832_IOCTL_SET_POWER_ON\n");
2068 if (copy_from_user(&mode,
2069 (const void __user *)arg,
2070 sizeof(struct ar0832_mode))) {
2071 dev_err(&i2c_client->dev,
2072 "%s: AR0832_IOCTL_SET_POWER_ON failed\n",
2073 __func__);
2074 return -EFAULT;
2075 }
2076 dev->is_stereo = mode.stereo;
2077 return ar0832_power_on(dev);
2078 case AR0832_IOCTL_SET_MODE:
2079 {
2080 dev_dbg(&i2c_client->dev, "AR0832_IOCTL_SET_MODE\n");
2081 if (copy_from_user(&mode,
2082 (const void __user *)arg,
2083 sizeof(struct ar0832_mode))) {
2084 dev_err(&i2c_client->dev,
2085 "%s: AR0832_IOCTL_SET_MODE failed\n",
2086 __func__);
2087 return -EFAULT;
2088 }
2089 mutex_lock(&dev->ar0832_camera_lock);
2090 err = ar0832_set_mode(dev, &mode);
2091
2092 /*
2093 * We need to re-initialize the Focuser registers during mode
2094 * switch due to the known issue of focuser retracting
2095 */
2096 ar0832_focuser_set_config(dev);
2097 dev->focuser_info->focuser_init_flag = true;
2098
2099 /*
2100 * If the last focuser position is not at infinity when we
2101 * did the mode switch, we need to go there. Before that,
2102 * we need to come back to 0.
2103 */
2104 if (dev->focuser_info->last_position > 0) {
2105 pos = dev->focuser_info->last_position;
2106 dev_dbg(&i2c_client->dev, "%s: AR0832_IOCTL_SET_MODE: "
2107 " Move to 0, restore the backedup focuser position of %d\n",
2108 __func__, pos);
2109 ar0832_focuser_set_position(dev, 0);
2110 ar0832_msleep(10);
2111
2112 ar0832_focuser_set_position(dev, pos);
2113 ar0832_msleep(10);
2114 }
2115 mutex_unlock(&dev->ar0832_camera_lock);
2116 return err;
2117 }
2118 case AR0832_IOCTL_SET_FRAME_LENGTH:
2119 mutex_lock(&dev->ar0832_camera_lock);
2120 err = ar0832_set_frame_length(dev, (u32)arg);
2121 mutex_unlock(&dev->ar0832_camera_lock);
2122 return err;
2123 case AR0832_IOCTL_SET_COARSE_TIME:
2124 mutex_lock(&dev->ar0832_camera_lock);
2125 err = ar0832_set_coarse_time(dev, (u32)arg);
2126 mutex_unlock(&dev->ar0832_camera_lock);
2127 return err;
2128 case AR0832_IOCTL_SET_GAIN:
2129 mutex_lock(&dev->ar0832_camera_lock);
2130 err = ar0832_set_gain(dev, (u16)arg);
2131 mutex_unlock(&dev->ar0832_camera_lock);
2132 return err;
2133 case AR0832_IOCTL_GET_STATUS:
2134 {
2135 u8 status;
2136 dev_dbg(&i2c_client->dev, "AR0832_IOCTL_GET_STATUS\n");
2137 err = ar0832_get_status(dev, &status);
2138 if (err)
2139 return err;
2140 if (copy_to_user((void __user *)arg, &status,
2141 2)) {
2142 dev_err(&i2c_client->dev,
2143 "%s: AR0832_IOCTL_GET_STATUS failed\n",
2144 __func__);
2145 return -EFAULT;
2146 }
2147 return 0;
2148 }
2149 case AR0832_IOCTL_SET_SENSOR_REGION:
2150 {
2151 struct ar0832_stereo_region region;
2152 dev_dbg(&i2c_client->dev, "AR0832_IOCTL_SET_SENSOR_REGION\n");
2153 /* Right now, it doesn't do anything */
2154
2155 return 0;
2156 }
2157
2158 case AR0832_FOCUSER_IOCTL_GET_CONFIG:
2159 dev_dbg(&i2c_client->dev,
2160 "%s AR0832_FOCUSER_IOCTL_GET_CONFIG\n", __func__);
2161 if (copy_to_user((void __user *) arg,
2162 &dev->focuser_info->config,
2163 sizeof(dev->focuser_info->config))) {
2164 dev_err(&i2c_client->dev,
2165 "%s: AR0832_FOCUSER_IOCTL_GET_CONFIG failed\n",
2166 __func__);
2167 return -EFAULT;
2168 }
2169 return 0;
2170
2171 case AR0832_FOCUSER_IOCTL_SET_POSITION:
2172 dev_dbg(&i2c_client->dev,
2173 "%s AR0832_FOCUSER_IOCTL_SET_POSITION\n", __func__);
2174 mutex_lock(&dev->ar0832_camera_lock);
2175 if (dev->focuser_info->focuser_init_flag == false) {
2176 ar0832_focuser_set_config(dev);
2177 dev->focuser_info->focuser_init_flag = true;
2178 }
2179 err = ar0832_focuser_set_position(dev, (u32)arg);
2180 mutex_unlock(&dev->ar0832_camera_lock);
2181 return err;
2182
2183 case AR0832_IOCTL_GET_SENSOR_ID:
2184 dev_dbg(&i2c_client->dev,
2185 "%s AR0832_IOCTL_GET_SENSOR_ID\n", __func__);
2186
2187 if (!dev->sensor_id_data) {
2188 err = ar0832_get_sensorid(dev, &dev->sensor_id_data);
2189 if (err) {
2190 dev_err(&i2c_client->dev,
2191 "%s: failed to get sensor id\n",
2192 __func__);
2193 return -EFAULT;
2194 }
2195 }
2196
2197 if (copy_to_user((void __user *) arg,
2198 &dev->sensor_id_data,
2199 sizeof(dev->sensor_id_data))) {
2200 dev_err(&i2c_client->dev,
2201 "%s: AR0832_IOCTL_GET_SENSOR_ID failed\n",
2202 __func__);
2203 return -EFAULT;
2204 }
2205 return 0;
2206
2207 default:
2208 dev_err(&i2c_client->dev, "(error) %s NONE IOCTL\n",
2209 __func__);
2210 return -EINVAL;
2211 }
2212 return 0;
2213}
2214
2215static int ar0832_open(struct inode *inode, struct file *file)
2216{
2217 struct miscdevice *miscdev = file->private_data;
2218 struct ar0832_dev *dev = dev_get_drvdata(miscdev->parent);
2219 struct i2c_client *i2c_client = dev->i2c_client;
2220
2221 dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
2222 if (atomic_xchg(&dev->in_use, 1))
2223 return -EBUSY;
2224
2225 dev->focuser_info->focuser_init_flag = false;
2226 file->private_data = dev;
2227
2228 return 0;
2229}
2230
2231static int ar0832_release(struct inode *inode, struct file *file)
2232{
2233 struct ar0832_dev *dev = file->private_data;
2234 struct i2c_client *i2c_client = dev->i2c_client;
2235
2236 dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
2237
2238 ar0832_power_off(dev);
2239
2240 file->private_data = NULL;
2241
2242 dev->focuser_info->focuser_init_flag = false;
2243
2244 WARN_ON(!atomic_xchg(&dev->in_use, 0));
2245 return 0;
2246}
2247
2248static const struct file_operations ar0832_fileops = {
2249 .owner = THIS_MODULE,
2250 .open = ar0832_open,
2251 .unlocked_ioctl = ar0832_ioctl,
2252 .release = ar0832_release,
2253};
2254
2255static int ar0832_debugfs_show(struct seq_file *s, void *unused)
2256{
2257 struct ar0832_dev *dev = s->private;
2258 struct i2c_client *i2c_client = dev->i2c_client;
2259 int ret;
2260 u16 test_pattern_reg;
2261
2262 dev_dbg(&dev->i2c_client->dev, "%s: ++\n", __func__);
2263 if (!dev->brd_power_cnt) {
2264 dev_info(&i2c_client->dev,
2265 "%s: camera is off\n", __func__);
2266 return 0;
2267 }
2268
2269 mutex_lock(&dev->ar0832_camera_lock);
2270 ret = ar0832_read_reg16(i2c_client,
2271 AR0832_TEST_PATTERN_REG, &test_pattern_reg);
2272 mutex_unlock(&dev->ar0832_camera_lock);
2273
2274 if (ret) {
2275 dev_err(&i2c_client->dev,
2276 "%s: test pattern write failed\n", __func__);
2277 return -EFAULT;
2278 }
2279
2280 seq_printf(s, "%d\n", test_pattern_reg);
2281 return 0;
2282}
2283
2284static ssize_t ar0832_debugfs_write(
2285 struct file *file,
2286 char const __user *buf,
2287 size_t count,
2288 loff_t *offset)
2289{
2290 struct ar0832_dev *dev = ((struct seq_file *)file->private_data)->private;
2291 struct i2c_client *i2c_client = dev->i2c_client;
2292 int ret = 0;
2293 char buffer[10];
2294 u16 input, val, red = 0, green = 0, blue = 0;
2295
2296 dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
2297 if (!dev->brd_power_cnt) {
2298 dev_info(&i2c_client->dev,
2299 "%s: camera is off\n", __func__);
2300 return count;
2301 }
2302
2303 if (copy_from_user(&buffer, buf, sizeof(buffer)))
2304 goto debugfs_write_fail;
2305
2306 input = (u16)simple_strtoul(buffer, NULL, 10);
2307
2308 mutex_lock(&dev->ar0832_camera_lock);
2309 ret = ar0832_write_reg8(i2c_client, AR0832_GROUP_HOLD_REG, 0x1);
2310
2311 switch (input) {
2312 case 1: /* color bar */
2313 val = 2;
2314 break;
2315 case 2: /* Red */
2316 val = 1;
2317 red = 0x300; /* 10 bit value */
2318 green = 0;
2319 blue = 0;
2320 break;
2321 case 3: /* Green */
2322 val = 1;
2323 red = 0;
2324 green = 0x300; /* 10 bit value */
2325 blue = 0;
2326 break;
2327 case 4: /* Blue */
2328 val = 1;
2329 red = 0;
2330 green = 0;
2331 blue = 0x300; /* 10 bit value */
2332 break;
2333 default:
2334 val = 0;
2335 break;
2336 }
2337
2338 if (input == 2 || input == 3 || input == 4) {
2339 ret |= ar0832_write_reg_helper(dev,
2340 AR0832_TEST_RED_REG, red);
2341 ret |= ar0832_write_reg_helper(dev,
2342 AR0832_TEST_GREENR_REG, green);
2343 ret |= ar0832_write_reg_helper(dev,
2344 AR0832_TEST_GREENR_REG, green);
2345 ret |= ar0832_write_reg_helper(dev,
2346 AR0832_TEST_BLUE_REG, blue);
2347 }
2348
2349 ret |= ar0832_write_reg_helper(dev, AR0832_TEST_PATTERN_REG, val);
2350 ret |= ar0832_write_reg8(i2c_client, AR0832_GROUP_HOLD_REG, 0x0);
2351 mutex_unlock(&dev->ar0832_camera_lock);
2352
2353 if (ret)
2354 goto debugfs_write_fail;
2355
2356 return count;
2357
2358debugfs_write_fail:
2359 dev_err(&i2c_client->dev,
2360 "%s: test pattern write failed\n", __func__);
2361 return -EFAULT;
2362}
2363
2364static int ar0832_debugfs_open(struct inode *inode, struct file *file)
2365{
2366 struct ar0832_dev *dev = inode->i_private;
2367 struct i2c_client *i2c_client = dev->i2c_client;
2368
2369 dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
2370
2371 return single_open(file, ar0832_debugfs_show, inode->i_private);
2372}
2373
2374static const struct file_operations ar0832_debugfs_fops = {
2375 .open = ar0832_debugfs_open,
2376 .read = seq_read,
2377 .write = ar0832_debugfs_write,
2378 .llseek = seq_lseek,
2379 .release = single_release,
2380};
2381
2382static void __devexit ar0832_remove_debugfs(struct ar0832_dev *dev)
2383{
2384 struct i2c_client *i2c_client = dev->i2c_client;
2385
2386 dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
2387
2388 if (dev->debugdir)
2389 debugfs_remove_recursive(dev->debugdir);
2390 dev->debugdir = NULL;
2391}
2392
2393static void ar0832_create_debugfs(struct ar0832_dev *dev)
2394{
2395 struct dentry *ret;
2396 struct i2c_client *i2c_client = dev->i2c_client;
2397
2398 dev_dbg(&i2c_client->dev, "%s\n", __func__);
2399
2400 dev->debugdir = debugfs_create_dir(dev->dname, NULL);
2401 if (!dev->debugdir)
2402 goto remove_debugfs;
2403
2404 ret = debugfs_create_file("test_pattern",
2405 S_IWUGO | S_IRUGO,
2406 dev->debugdir, dev,
2407 &ar0832_debugfs_fops);
2408 if (!ret)
2409 goto remove_debugfs;
2410
2411 return;
2412remove_debugfs:
2413 dev_err(&i2c_client->dev, "couldn't create debugfs\n");
2414 ar0832_remove_debugfs(dev);
2415}
2416
2417static int ar0832_probe(struct i2c_client *client,
2418 const struct i2c_device_id *id)
2419{
2420 int err;
2421 struct ar0832_dev *dev = NULL;
2422 int ret;
2423
2424 dev_info(&client->dev, "ar0832: probing sensor.(id:%s)\n",
2425 id->name);
2426
2427 dev = kzalloc(sizeof(struct ar0832_dev), GFP_KERNEL);
2428 if (!dev)
2429 goto probe_fail_release;
2430
2431 dev->sensor_info = kzalloc(sizeof(struct ar0832_sensor_info),
2432 GFP_KERNEL);
2433 if (!dev->sensor_info)
2434 goto probe_fail_release;
2435
2436 dev->focuser_info = kzalloc(sizeof(struct ar0832_focuser_info),
2437 GFP_KERNEL);
2438 if (!dev->focuser_info)
2439 goto probe_fail_release;
2440
2441 /* sensor */
2442 dev->pdata = client->dev.platform_data;
2443 dev->i2c_client = client;
2444
2445 /* focuser */
2446 dev->focuser_info->config.settle_time = SETTLETIME_MS;
2447 dev->focuser_info->config.pos_low = POS_LOW;
2448 dev->focuser_info->config.pos_high = POS_HIGH;
2449
2450 snprintf(dev->dname, sizeof(dev->dname), "%s-%s",
2451 id->name, dev->pdata->id);
2452 dev->misc_dev.minor = MISC_DYNAMIC_MINOR;
2453 dev->misc_dev.name = dev->dname;
2454 dev->misc_dev.fops = &ar0832_fileops;
2455 dev->misc_dev.mode = S_IRWXUGO;
2456 dev->misc_dev.parent = &client->dev;
2457 err = misc_register(&dev->misc_dev);
2458 if (err) {
2459 dev_err(&client->dev, "Unable to register misc device!\n");
2460 ret = -ENOMEM;
2461 goto probe_fail_free;
2462 }
2463
2464 i2c_set_clientdata(client, dev);
2465 mutex_init(&dev->ar0832_camera_lock);
2466
2467 dev->power_rail.sen_1v8_reg = regulator_get(&client->dev, "vdd");
2468 if (IS_ERR_OR_NULL(dev->power_rail.sen_1v8_reg)) {
2469 dev_err(&client->dev, "%s: failed to get vdd\n",
2470 __func__);
2471 ret = PTR_ERR(dev->power_rail.sen_1v8_reg);
2472 goto probe_fail_free;
2473 }
2474
2475 dev->power_rail.sen_2v8_reg = regulator_get(&client->dev, "vaa");
2476 if (IS_ERR_OR_NULL(dev->power_rail.sen_2v8_reg)) {
2477 dev_err(&client->dev, "%s: failed to get vaa\n",
2478 __func__);
2479 ret = PTR_ERR(dev->power_rail.sen_2v8_reg);
2480 regulator_put(dev->power_rail.sen_1v8_reg);
2481 dev->power_rail.sen_1v8_reg = NULL;
2482 goto probe_fail_free;
2483 }
2484 /* create debugfs interface */
2485 ar0832_create_debugfs(dev);
2486
2487 return 0;
2488
2489probe_fail_release:
2490 dev_err(&client->dev, "%s: unable to allocate memory!\n", __func__);
2491 ret = -ENOMEM;
2492probe_fail_free:
2493 if (dev) {
2494 kfree(dev->focuser_info);
2495 kfree(dev->sensor_info);
2496 }
2497 kfree(dev);
2498 return ret;
2499}
2500
2501static int ar0832_remove(struct i2c_client *client)
2502{
2503 struct ar0832_dev *dev = i2c_get_clientdata(client);
2504
2505 if (dev->power_rail.sen_1v8_reg)
2506 regulator_put(dev->power_rail.sen_1v8_reg);
2507 if (dev->power_rail.sen_2v8_reg)
2508 regulator_put(dev->power_rail.sen_2v8_reg);
2509
2510 misc_deregister(&dev->misc_dev);
2511 if (dev) {
2512 kfree(dev->sensor_info);
2513 kfree(dev->focuser_info);
2514 }
2515
2516 ar0832_remove_debugfs(dev);
2517
2518 kfree(dev);
2519 return 0;
2520}
2521
2522static const struct i2c_device_id ar0832_id[] = {
2523 { "ar0832", 0 },
2524 { }
2525};
2526
2527static struct i2c_driver ar0832_i2c_driver = {
2528 .probe = ar0832_probe,
2529 .remove = ar0832_remove,
2530 .id_table = ar0832_id,
2531 .driver = {
2532 .name = "ar0832",
2533 .owner = THIS_MODULE,
2534 },
2535};
2536
2537static int __init ar0832_init(void)
2538{
2539 pr_info("%s: ++\n", __func__);
2540 return i2c_add_driver(&ar0832_i2c_driver);
2541}
2542
2543static void __exit ar0832_exit(void)
2544{
2545 i2c_del_driver(&ar0832_i2c_driver);
2546}
2547
2548module_init(ar0832_init);
2549module_exit(ar0832_exit);
diff --git a/drivers/media/video/tegra/avp/Kconfig b/drivers/media/video/tegra/avp/Kconfig
new file mode 100644
index 00000000000..fdd208510fc
--- /dev/null
+++ b/drivers/media/video/tegra/avp/Kconfig
@@ -0,0 +1,25 @@
1config TEGRA_RPC
2 bool "Enable support for Tegra RPC"
3 depends on ARCH_TEGRA
4 default y
5 help
6 Enables support for the RPC mechanism necessary for the Tegra
7 multimedia framework. It is both used to communicate locally on the
8 CPU between multiple multimedia components as well as to communicate
9 with the AVP for offloading media decode.
10
11 Exports the local tegra RPC interface on device node
12 /dev/tegra_rpc. Also provides tegra fd based semaphores needed by
13 the tegra multimedia framework.
14
15 If unsure, say Y
16
17config TEGRA_AVP
18 bool "Enable support for the AVP multimedia offload engine"
19 depends on ARCH_TEGRA && TEGRA_RPC
20 default y
21 help
22 Enables support for the multimedia offload engine used by Tegra
23 multimedia framework.
24
25 If unsure, say Y
diff --git a/drivers/media/video/tegra/avp/Makefile b/drivers/media/video/tegra/avp/Makefile
new file mode 100644
index 00000000000..148265648a4
--- /dev/null
+++ b/drivers/media/video/tegra/avp/Makefile
@@ -0,0 +1,7 @@
1GCOV_PROFILE := y
2obj-$(CONFIG_TEGRA_RPC) += tegra_rpc.o
3obj-$(CONFIG_TEGRA_RPC) += trpc_local.o
4obj-$(CONFIG_TEGRA_RPC) += trpc_sema.o
5obj-$(CONFIG_TEGRA_AVP) += avp.o
6obj-$(CONFIG_TEGRA_AVP) += avp_svc.o
7obj-$(CONFIG_TEGRA_AVP) += headavp.o
diff --git a/drivers/media/video/tegra/avp/avp.c b/drivers/media/video/tegra/avp/avp.c
new file mode 100644
index 00000000000..074a42f125b
--- /dev/null
+++ b/drivers/media/video/tegra/avp/avp.c
@@ -0,0 +1,1949 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 * Author: Dima Zavin <dima@android.com>
4 *
5 * Copyright (C) 2010-2012 NVIDIA Corporation
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/clk.h>
19#include <linux/completion.h>
20#include <linux/delay.h>
21#include <linux/dma-mapping.h>
22#include <linux/err.h>
23#include <linux/firmware.h>
24#include <linux/fs.h>
25#include <linux/interrupt.h>
26#include <linux/io.h>
27#include <linux/ioctl.h>
28#include <linux/irq.h>
29#include <linux/kref.h>
30#include <linux/list.h>
31#include <linux/miscdevice.h>
32#include <linux/mutex.h>
33#include <linux/platform_device.h>
34#include <linux/rbtree.h>
35#include <linux/seq_file.h>
36#include <linux/slab.h>
37#include <linux/tegra_rpc.h>
38#include <linux/types.h>
39#include <linux/uaccess.h>
40#include <linux/workqueue.h>
41
42#include <mach/clk.h>
43#include <mach/io.h>
44#include <mach/iomap.h>
45#include <mach/nvmap.h>
46#include <mach/legacy_irq.h>
47#include <mach/hardware.h>
48
49#include "../../../../video/tegra/nvmap/nvmap.h"
50
51#include "headavp.h"
52#include "avp_msg.h"
53#include "trpc.h"
54#include "avp.h"
55#include "nvavp.h"
56
57enum {
58 AVP_DBG_TRACE_XPC = 1U << 0,
59 AVP_DBG_TRACE_XPC_IRQ = 1U << 1,
60 AVP_DBG_TRACE_XPC_MSG = 1U << 2,
61 AVP_DBG_TRACE_XPC_CONN = 1U << 3,
62 AVP_DBG_TRACE_TRPC_MSG = 1U << 4,
63 AVP_DBG_TRACE_TRPC_CONN = 1U << 5,
64 AVP_DBG_TRACE_LIB = 1U << 6,
65};
66
67static u32 avp_debug_mask =
68 AVP_DBG_TRACE_XPC |
69 /* AVP_DBG_TRACE_XPC_IRQ | */
70 /* AVP_DBG_TRACE_XPC_MSG | */
71 /* AVP_DBG_TRACE_TRPC_MSG | */
72 AVP_DBG_TRACE_XPC_CONN |
73 AVP_DBG_TRACE_TRPC_CONN |
74 AVP_DBG_TRACE_LIB;
75
76module_param_named(debug_mask, avp_debug_mask, uint, S_IWUSR | S_IRUGO);
77
78#define DBG(flag, args...) \
79 do { if (unlikely(avp_debug_mask & (flag))) pr_info(args); } while (0)
80
81#define TEGRA_AVP_NAME "tegra-avp"
82
83#define TEGRA_AVP_RESET_VECTOR_ADDR \
84 (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x200)
85
86#define TEGRA_AVP_RESUME_ADDR IO_ADDRESS(TEGRA_IRAM_BASE + \
87 TEGRA_RESET_HANDLER_SIZE)
88
89#define FLOW_CTRL_HALT_COP_EVENTS IO_ADDRESS(TEGRA_FLOW_CTRL_BASE + 0x4)
90#define FLOW_MODE_STOP (0x2 << 29)
91#define FLOW_MODE_NONE 0x0
92
93#define MBOX_FROM_AVP IO_ADDRESS(TEGRA_RES_SEMA_BASE + 0x10)
94#define MBOX_TO_AVP IO_ADDRESS(TEGRA_RES_SEMA_BASE + 0x20)
95
96/* Layout of the mailbox registers:
97 * bit 31 - pending message interrupt enable (mailbox full, i.e. valid=1)
98 * bit 30 - message cleared interrupt enable (mailbox empty, i.e. valid=0)
99 * bit 29 - message valid. peer clears this bit after reading msg
100 * bits 27:0 - message data
101 */
102#define MBOX_MSG_PENDING_INT_EN (1 << 31)
103#define MBOX_MSG_READ_INT_EN (1 << 30)
104#define MBOX_MSG_VALID (1 << 29)
105
106#define AVP_MSG_MAX_CMD_LEN 16
107#define AVP_MSG_AREA_SIZE (AVP_MSG_MAX_CMD_LEN + TEGRA_RPC_MAX_MSG_LEN)
108
109struct tegra_avp_info {
110 struct clk *cop_clk;
111
112 int mbox_from_avp_pend_irq;
113
114 dma_addr_t msg_area_addr;
115 u32 msg;
116 void *msg_to_avp;
117 void *msg_from_avp;
118 struct mutex to_avp_lock;
119 struct mutex from_avp_lock;
120
121 struct work_struct recv_work;
122 struct workqueue_struct *recv_wq;
123
124 struct trpc_node *rpc_node;
125 struct miscdevice misc_dev;
126 int refcount;
127 struct mutex open_lock;
128
129 spinlock_t state_lock;
130 bool initialized;
131 bool shutdown;
132 bool suspending;
133 bool defer_remote;
134
135 struct mutex libs_lock;
136 struct list_head libs;
137 struct nvmap_client *nvmap_libs;
138
139 /* client for driver allocations, persistent */
140 struct nvmap_client *nvmap_drv;
141 struct nvmap_handle_ref *kernel_handle;
142 void *kernel_data;
143 phys_addr_t kernel_phys;
144
145 struct nvmap_handle_ref *iram_backup_handle;
146 void *iram_backup_data;
147 phys_addr_t iram_backup_phys;
148 unsigned long resume_addr;
149 unsigned long reset_addr;
150
151 struct trpc_endpoint *avp_ep;
152 struct rb_root endpoints;
153
154 struct avp_svc_info *avp_svc;
155};
156
157struct remote_info {
158 u32 loc_id;
159 u32 rem_id;
160 struct kref ref;
161
162 struct trpc_endpoint *trpc_ep;
163 struct rb_node rb_node;
164};
165
166struct lib_item {
167 struct list_head list;
168 u32 handle;
169 char name[TEGRA_AVP_LIB_MAX_NAME];
170};
171
172static struct tegra_avp_info *tegra_avp;
173
174static int avp_trpc_send(struct trpc_endpoint *ep, void *buf, size_t len);
175static void avp_trpc_close(struct trpc_endpoint *ep);
176static void avp_trpc_show(struct seq_file *s, struct trpc_endpoint *ep);
177static void libs_cleanup(struct tegra_avp_info *avp);
178
179static struct trpc_ep_ops remote_ep_ops = {
180 .send = avp_trpc_send,
181 .close = avp_trpc_close,
182 .show = avp_trpc_show,
183};
184
185static struct remote_info *rinfo_alloc(struct tegra_avp_info *avp)
186{
187 struct remote_info *rinfo;
188
189 rinfo = kzalloc(sizeof(struct remote_info), GFP_KERNEL);
190 if (!rinfo)
191 return NULL;
192 kref_init(&rinfo->ref);
193 return rinfo;
194}
195
196static void _rinfo_release(struct kref *ref)
197{
198 struct remote_info *rinfo = container_of(ref, struct remote_info, ref);
199 kfree(rinfo);
200}
201
202static inline void rinfo_get(struct remote_info *rinfo)
203{
204 kref_get(&rinfo->ref);
205}
206
207static inline void rinfo_put(struct remote_info *rinfo)
208{
209 kref_put(&rinfo->ref, _rinfo_release);
210}
211
212static int remote_insert(struct tegra_avp_info *avp, struct remote_info *rinfo)
213{
214 struct rb_node **p;
215 struct rb_node *parent;
216 struct remote_info *tmp;
217
218 p = &avp->endpoints.rb_node;
219 parent = NULL;
220 while (*p) {
221 parent = *p;
222 tmp = rb_entry(parent, struct remote_info, rb_node);
223
224 if (rinfo->loc_id < tmp->loc_id)
225 p = &(*p)->rb_left;
226 else if (rinfo->loc_id > tmp->loc_id)
227 p = &(*p)->rb_right;
228 else {
229 pr_info("%s: avp endpoint id=%x (%s) already exists\n",
230 __func__, rinfo->loc_id,
231 trpc_name(rinfo->trpc_ep));
232 return -EEXIST;
233 }
234 }
235 rb_link_node(&rinfo->rb_node, parent, p);
236 rb_insert_color(&rinfo->rb_node, &avp->endpoints);
237 rinfo_get(rinfo);
238 return 0;
239}
240
241static struct remote_info *remote_find(struct tegra_avp_info *avp, u32 local_id)
242{
243 struct rb_node *n = avp->endpoints.rb_node;
244 struct remote_info *rinfo;
245
246 while (n) {
247 rinfo = rb_entry(n, struct remote_info, rb_node);
248
249 if (local_id < rinfo->loc_id)
250 n = n->rb_left;
251 else if (local_id > rinfo->loc_id)
252 n = n->rb_right;
253 else
254 return rinfo;
255 }
256 return NULL;
257}
258
259static void remote_remove(struct tegra_avp_info *avp, struct remote_info *rinfo)
260{
261 rb_erase(&rinfo->rb_node, &avp->endpoints);
262 rinfo_put(rinfo);
263}
264
265/* test whether or not the trpc endpoint provided is a valid AVP node
266 * endpoint */
267static struct remote_info *validate_trpc_ep(struct tegra_avp_info *avp,
268 struct trpc_endpoint *ep)
269{
270 struct remote_info *tmp = trpc_priv(ep);
271 struct remote_info *rinfo;
272
273 if (!tmp)
274 return NULL;
275 rinfo = remote_find(avp, tmp->loc_id);
276 if (rinfo && rinfo == tmp && rinfo->trpc_ep == ep)
277 return rinfo;
278 return NULL;
279}
280
281static void avp_trpc_show(struct seq_file *s, struct trpc_endpoint *ep)
282{
283 struct tegra_avp_info *avp = tegra_avp;
284 struct remote_info *rinfo;
285 unsigned long flags;
286
287 spin_lock_irqsave(&avp->state_lock, flags);
288 rinfo = validate_trpc_ep(avp, ep);
289 if (!rinfo) {
290 seq_printf(s, " <unknown>\n");
291 goto out;
292 }
293 seq_printf(s, " loc_id:0x%x\n rem_id:0x%x\n",
294 rinfo->loc_id, rinfo->rem_id);
295out:
296 spin_unlock_irqrestore(&avp->state_lock, flags);
297}
298
299static inline void mbox_writel(u32 val, void __iomem *mbox)
300{
301 writel(val, mbox);
302}
303
304static inline u32 mbox_readl(void __iomem *mbox)
305{
306 return readl(mbox);
307}
308
309static inline void msg_ack_remote(struct tegra_avp_info *avp, u32 cmd, u32 arg)
310{
311 struct msg_ack *ack = avp->msg_from_avp;
312
313 /* must make sure the arg is there first */
314 ack->arg = arg;
315 wmb();
316 ack->cmd = cmd;
317 wmb();
318}
319
320static inline u32 msg_recv_get_cmd(struct tegra_avp_info *avp)
321{
322 volatile u32 *cmd = avp->msg_from_avp;
323 rmb();
324 return *cmd;
325}
326
327static inline int __msg_write(struct tegra_avp_info *avp, void *hdr,
328 size_t hdr_len, void *buf, size_t len)
329{
330 memcpy(avp->msg_to_avp, hdr, hdr_len);
331 if (buf && len)
332 memcpy(avp->msg_to_avp + hdr_len, buf, len);
333 mbox_writel(avp->msg, MBOX_TO_AVP);
334 return 0;
335}
336
337static inline int msg_write(struct tegra_avp_info *avp, void *hdr,
338 size_t hdr_len, void *buf, size_t len)
339{
340 /* rem_ack is a pointer into shared memory that the AVP modifies */
341 volatile u32 *rem_ack = avp->msg_to_avp;
342 unsigned long endtime = jiffies + HZ;
343
344 /* the other side ack's the message by clearing the first word,
345 * wait for it to do so */
346 rmb();
347 while (*rem_ack != 0 && time_before(jiffies, endtime)) {
348 usleep_range(100, 2000);
349 rmb();
350 }
351 if (*rem_ack != 0)
352 return -ETIMEDOUT;
353 __msg_write(avp, hdr, hdr_len, buf, len);
354 return 0;
355}
356
357static inline int msg_check_ack(struct tegra_avp_info *avp, u32 cmd, u32 *arg)
358{
359 struct msg_ack ack;
360
361 rmb();
362 memcpy(&ack, avp->msg_to_avp, sizeof(ack));
363 if (ack.cmd != cmd)
364 return -ENOENT;
365 if (arg)
366 *arg = ack.arg;
367 return 0;
368}
369
370/* XXX: add timeout */
371static int msg_wait_ack_locked(struct tegra_avp_info *avp, u32 cmd, u32 *arg)
372{
373 /* rem_ack is a pointer into shared memory that the AVP modifies */
374 volatile u32 *rem_ack = avp->msg_to_avp;
375 unsigned long endtime = jiffies + msecs_to_jiffies(400);
376 int ret;
377
378 do {
379 ret = msg_check_ack(avp, cmd, arg);
380 usleep_range(1000, 5000);
381 } while (ret && time_before(jiffies, endtime));
382
383 /* if we timed out, try one more time */
384 if (ret)
385 ret = msg_check_ack(avp, cmd, arg);
386
387 /* clear out the ack */
388 *rem_ack = 0;
389 wmb();
390 return ret;
391}
392
393static int avp_trpc_send(struct trpc_endpoint *ep, void *buf, size_t len)
394{
395 struct tegra_avp_info *avp = tegra_avp;
396 struct remote_info *rinfo;
397 struct msg_port_data msg;
398 int ret;
399 unsigned long flags;
400
401 DBG(AVP_DBG_TRACE_TRPC_MSG, "%s: ep=%p priv=%p buf=%p len=%d\n",
402 __func__, ep, trpc_priv(ep), buf, len);
403
404 spin_lock_irqsave(&avp->state_lock, flags);
405 if (unlikely(avp->suspending && trpc_peer(ep) != avp->avp_ep)) {
406 ret = -EBUSY;
407 goto err_state_locked;
408 } else if (avp->shutdown) {
409 ret = -ENODEV;
410 goto err_state_locked;
411 }
412 rinfo = validate_trpc_ep(avp, ep);
413 if (!rinfo) {
414 ret = -ENOTTY;
415 goto err_state_locked;
416 }
417 rinfo_get(rinfo);
418 spin_unlock_irqrestore(&avp->state_lock, flags);
419
420 msg.cmd = CMD_MESSAGE;
421 msg.port_id = rinfo->rem_id;
422 msg.msg_len = len;
423
424 mutex_lock(&avp->to_avp_lock);
425 ret = msg_write(avp, &msg, sizeof(msg), buf, len);
426 mutex_unlock(&avp->to_avp_lock);
427
428 DBG(AVP_DBG_TRACE_TRPC_MSG, "%s: msg sent for %s (%x->%x) (%d)\n",
429 __func__, trpc_name(ep), rinfo->loc_id, rinfo->rem_id, ret);
430 rinfo_put(rinfo);
431 return ret;
432
433err_state_locked:
434 spin_unlock_irqrestore(&avp->state_lock, flags);
435 return ret;
436}
437
438static int _send_disconnect(struct tegra_avp_info *avp, u32 port_id)
439{
440 struct msg_disconnect msg;
441 int ret;
442
443 msg.cmd = CMD_DISCONNECT;
444 msg.port_id = port_id;
445
446 mutex_lock(&avp->to_avp_lock);
447 ret = msg_write(avp, &msg, sizeof(msg), NULL, 0);
448 if (ret) {
449 pr_err("%s: remote has not acked last message (%x)\n", __func__,
450 port_id);
451 goto err_msg_write;
452 }
453
454 ret = msg_wait_ack_locked(avp, CMD_ACK, NULL);
455 if (ret) {
456 pr_err("%s: remote end won't respond for %x\n", __func__,
457 port_id);
458 goto err_wait_ack;
459 }
460
461 DBG(AVP_DBG_TRACE_XPC_CONN, "%s: sent disconnect msg for %x\n",
462 __func__, port_id);
463
464err_wait_ack:
465err_msg_write:
466 mutex_unlock(&avp->to_avp_lock);
467 return ret;
468}
469
470/* Note: Assumes that the rinfo was previously successfully added to the
471 * endpoints rb_tree. The initial refcnt of 1 is inherited by the port when the
472 * trpc endpoint is created with thi trpc_xxx functions. Thus, on close,
473 * we must drop that reference here.
474 * The avp->endpoints rb_tree keeps its own reference on rinfo objects.
475 *
476 * The try_connect function does not use this on error because it needs to
477 * split the close of trpc_ep port and the put.
478 */
479static inline void remote_close(struct remote_info *rinfo)
480{
481 trpc_close(rinfo->trpc_ep);
482 rinfo_put(rinfo);
483}
484
485static void avp_trpc_close(struct trpc_endpoint *ep)
486{
487 struct tegra_avp_info *avp = tegra_avp;
488 struct remote_info *rinfo;
489 unsigned long flags;
490 int ret;
491
492 spin_lock_irqsave(&avp->state_lock, flags);
493 if (avp->shutdown) {
494 spin_unlock_irqrestore(&avp->state_lock, flags);
495 return;
496 }
497
498 rinfo = validate_trpc_ep(avp, ep);
499 if (!rinfo) {
500 pr_err("%s: tried to close invalid port '%s' endpoint (%p)\n",
501 __func__, trpc_name(ep), ep);
502 spin_unlock_irqrestore(&avp->state_lock, flags);
503 return;
504 }
505 rinfo_get(rinfo);
506 remote_remove(avp, rinfo);
507 spin_unlock_irqrestore(&avp->state_lock, flags);
508
509 DBG(AVP_DBG_TRACE_TRPC_CONN, "%s: closing '%s' (%x)\n", __func__,
510 trpc_name(ep), rinfo->rem_id);
511
512 ret = _send_disconnect(avp, rinfo->rem_id);
513 if (ret)
514 pr_err("%s: error while closing remote port '%s' (%x)\n",
515 __func__, trpc_name(ep), rinfo->rem_id);
516 remote_close(rinfo);
517 rinfo_put(rinfo);
518}
519
520/* takes and holds avp->from_avp_lock */
521static void recv_msg_lock(struct tegra_avp_info *avp)
522{
523 unsigned long flags;
524
525 mutex_lock(&avp->from_avp_lock);
526 spin_lock_irqsave(&avp->state_lock, flags);
527 avp->defer_remote = true;
528 spin_unlock_irqrestore(&avp->state_lock, flags);
529}
530
531/* MUST be called with avp->from_avp_lock held */
532static void recv_msg_unlock(struct tegra_avp_info *avp)
533{
534 unsigned long flags;
535
536 spin_lock_irqsave(&avp->state_lock, flags);
537 avp->defer_remote = false;
538 spin_unlock_irqrestore(&avp->state_lock, flags);
539 mutex_unlock(&avp->from_avp_lock);
540}
541
542static int avp_node_try_connect(struct trpc_node *node,
543 struct trpc_node *src_node,
544 struct trpc_endpoint *from)
545{
546 struct tegra_avp_info *avp = tegra_avp;
547 const char *port_name = trpc_name(from);
548 struct remote_info *rinfo;
549 struct msg_connect msg;
550 int ret;
551 unsigned long flags;
552 int len;
553 const int max_retry_cnt = 6;
554 int cnt = 0;
555
556 DBG(AVP_DBG_TRACE_TRPC_CONN, "%s: trying connect from %s\n", __func__,
557 port_name);
558
559 if (node != avp->rpc_node || node->priv != avp)
560 return -ENODEV;
561
562 len = strlen(port_name);
563 if (len > XPC_PORT_NAME_LEN) {
564 pr_err("%s: port name (%s) too long\n", __func__, port_name);
565 return -EINVAL;
566 }
567
568 ret = 0;
569 spin_lock_irqsave(&avp->state_lock, flags);
570 if (avp->suspending) {
571 ret = -EBUSY;
572 } else if (likely(src_node != avp->rpc_node)) {
573 /* only check for initialized when the source is not ourselves
574 * since we'll end up calling into here during initialization */
575 if (!avp->initialized)
576 ret = -ENODEV;
577 } else if (strncmp(port_name, "RPC_AVP_PORT", XPC_PORT_NAME_LEN)) {
578 /* we only allow connections to ourselves for the cpu-to-avp
579 port */
580 ret = -EINVAL;
581 }
582 spin_unlock_irqrestore(&avp->state_lock, flags);
583 if (ret)
584 return ret;
585
586 rinfo = rinfo_alloc(avp);
587 if (!rinfo) {
588 pr_err("%s: cannot alloc mem for rinfo\n", __func__);
589 ret = -ENOMEM;
590 goto err_alloc_rinfo;
591 }
592 rinfo->loc_id = (u32)rinfo;
593
594 msg.cmd = CMD_CONNECT;
595 msg.port_id = rinfo->loc_id;
596 memcpy(msg.name, port_name, len);
597 memset(msg.name + len, 0, XPC_PORT_NAME_LEN - len);
598
599 /* when trying to connect to remote, we need to block remote
600 * messages until we get our ack and can insert it into our lists.
601 * Otherwise, we can get a message from the other side for a port
602 * that we haven't finished setting up.
603 *
604 * 'defer_remote' will force the irq handler to not process messages
605 * at irq context but to schedule work to do so. The work function will
606 * take the from_avp_lock and everything should stay consistent.
607 */
608 recv_msg_lock(avp);
609 for (cnt = 0; cnt < max_retry_cnt; cnt++) {
610 /* Retry to connect to AVP at this function maximum 6 times.
611 * Because this section is protected by mutex and
612 * needed to re-send the CMD_CONNECT command by CPU
613 * if AVP didn't receive the command.
614 */
615 mutex_lock(&avp->to_avp_lock);
616 ret = msg_write(avp, &msg, sizeof(msg), NULL, 0);
617 if (ret) {
618 pr_err("%s: remote has not acked last message (%s)\n",
619 __func__, port_name);
620 mutex_unlock(&avp->to_avp_lock);
621 goto err_msg_write;
622 }
623 ret = msg_wait_ack_locked(avp, CMD_RESPONSE, &rinfo->rem_id);
624 mutex_unlock(&avp->to_avp_lock);
625 if (!ret && rinfo->rem_id)
626 break;
627
628 /* Skip the sleep function at last retry count */
629 if ((cnt + 1) < max_retry_cnt)
630 usleep_range(100, 2000);
631 }
632
633 if (ret) {
634 pr_err("%s: remote end won't respond for '%s'\n", __func__,
635 port_name);
636 goto err_wait_ack;
637 }
638 if (!rinfo->rem_id) {
639 pr_err("%s: can't connect to '%s'\n", __func__, port_name);
640 ret = -ECONNREFUSED;
641 goto err_nack;
642 }
643
644 DBG(AVP_DBG_TRACE_TRPC_CONN, "%s: got conn ack '%s' (%x <-> %x)\n",
645 __func__, port_name, rinfo->loc_id, rinfo->rem_id);
646
647 rinfo->trpc_ep = trpc_create_peer(node, from, &remote_ep_ops,
648 rinfo);
649 if (!rinfo->trpc_ep) {
650 pr_err("%s: cannot create peer for %s\n", __func__, port_name);
651 ret = -EINVAL;
652 goto err_create_peer;
653 }
654
655 spin_lock_irqsave(&avp->state_lock, flags);
656 ret = remote_insert(avp, rinfo);
657 spin_unlock_irqrestore(&avp->state_lock, flags);
658 if (ret)
659 goto err_ep_insert;
660
661 recv_msg_unlock(avp);
662 return 0;
663
664err_ep_insert:
665 trpc_close(rinfo->trpc_ep);
666err_create_peer:
667 _send_disconnect(avp, rinfo->rem_id);
668err_nack:
669err_wait_ack:
670err_msg_write:
671 recv_msg_unlock(avp);
672 rinfo_put(rinfo);
673err_alloc_rinfo:
674 return ret;
675}
676
677static void process_disconnect_locked(struct tegra_avp_info *avp,
678 struct msg_data *raw_msg)
679{
680 struct msg_disconnect *disconn_msg = (struct msg_disconnect *)raw_msg;
681 unsigned long flags;
682 struct remote_info *rinfo;
683
684 DBG(AVP_DBG_TRACE_XPC_CONN, "%s: got disconnect (%x)\n", __func__,
685 disconn_msg->port_id);
686
687 if (avp_debug_mask & AVP_DBG_TRACE_XPC_MSG)
688 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, disconn_msg,
689 sizeof(struct msg_disconnect));
690
691 spin_lock_irqsave(&avp->state_lock, flags);
692 rinfo = remote_find(avp, disconn_msg->port_id);
693 if (!rinfo) {
694 spin_unlock_irqrestore(&avp->state_lock, flags);
695 pr_warning("%s: got disconnect for unknown port %x\n",
696 __func__, disconn_msg->port_id);
697 goto ack;
698 }
699 rinfo_get(rinfo);
700 remote_remove(avp, rinfo);
701 spin_unlock_irqrestore(&avp->state_lock, flags);
702
703 remote_close(rinfo);
704 rinfo_put(rinfo);
705ack:
706 msg_ack_remote(avp, CMD_ACK, 0);
707}
708
709static void process_connect_locked(struct tegra_avp_info *avp,
710 struct msg_data *raw_msg)
711{
712 struct msg_connect *conn_msg = (struct msg_connect *)raw_msg;
713 struct trpc_endpoint *trpc_ep;
714 struct remote_info *rinfo;
715 char name[XPC_PORT_NAME_LEN + 1];
716 int ret;
717 u32 local_port_id = 0;
718 unsigned long flags;
719
720 DBG(AVP_DBG_TRACE_XPC_CONN, "%s: got connect (%x)\n", __func__,
721 conn_msg->port_id);
722 if (avp_debug_mask & AVP_DBG_TRACE_XPC_MSG)
723 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
724 conn_msg, sizeof(struct msg_connect));
725
726 rinfo = rinfo_alloc(avp);
727 if (!rinfo) {
728 pr_err("%s: cannot alloc mem for rinfo\n", __func__);
729 ret = -ENOMEM;
730 goto ack;
731 }
732 rinfo->loc_id = (u32)rinfo;
733 rinfo->rem_id = conn_msg->port_id;
734
735 memcpy(name, conn_msg->name, XPC_PORT_NAME_LEN);
736 name[XPC_PORT_NAME_LEN] = '\0';
737 trpc_ep = trpc_create_connect(avp->rpc_node, name, &remote_ep_ops,
738 rinfo, 0);
739 if (IS_ERR(trpc_ep)) {
740 pr_err("%s: remote requested unknown port '%s' (%d)\n",
741 __func__, name, (int)PTR_ERR(trpc_ep));
742 goto nack;
743 }
744 rinfo->trpc_ep = trpc_ep;
745
746 spin_lock_irqsave(&avp->state_lock, flags);
747 ret = remote_insert(avp, rinfo);
748 spin_unlock_irqrestore(&avp->state_lock, flags);
749 if (ret)
750 goto err_ep_insert;
751
752 local_port_id = rinfo->loc_id;
753 goto ack;
754
755err_ep_insert:
756 trpc_close(trpc_ep);
757nack:
758 rinfo_put(rinfo);
759 local_port_id = 0;
760ack:
761 msg_ack_remote(avp, CMD_RESPONSE, local_port_id);
762}
763
764static int process_message(struct tegra_avp_info *avp, struct msg_data *raw_msg,
765 gfp_t gfp_flags)
766{
767 struct msg_port_data *port_msg = (struct msg_port_data *)raw_msg;
768 struct remote_info *rinfo;
769 unsigned long flags;
770 int len;
771 int ret;
772
773 len = min(port_msg->msg_len, (u32)TEGRA_RPC_MAX_MSG_LEN);
774
775 if (avp_debug_mask & AVP_DBG_TRACE_XPC_MSG) {
776 pr_info("%s: got message cmd=%x port=%x len=%d\n", __func__,
777 port_msg->cmd, port_msg->port_id, port_msg->msg_len);
778 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, port_msg,
779 sizeof(struct msg_port_data) + len);
780 }
781
782 if (len != port_msg->msg_len)
783 pr_err("%s: message sent is too long (%d bytes)\n", __func__,
784 port_msg->msg_len);
785
786 spin_lock_irqsave(&avp->state_lock, flags);
787 rinfo = remote_find(avp, port_msg->port_id);
788 if (rinfo) {
789 rinfo_get(rinfo);
790 trpc_get(rinfo->trpc_ep);
791 } else {
792 pr_err("%s: port %x not found\n", __func__, port_msg->port_id);
793 spin_unlock_irqrestore(&avp->state_lock, flags);
794 ret = -ENOENT;
795 goto ack;
796 }
797 spin_unlock_irqrestore(&avp->state_lock, flags);
798
799 ret = trpc_send_msg(avp->rpc_node, rinfo->trpc_ep, port_msg->data,
800 len, gfp_flags);
801 if (ret == -ENOMEM) {
802 trpc_put(rinfo->trpc_ep);
803 rinfo_put(rinfo);
804 goto no_ack;
805 } else if (ret) {
806 pr_err("%s: cannot queue message for port %s/%x (%d)\n",
807 __func__, trpc_name(rinfo->trpc_ep), rinfo->loc_id,
808 ret);
809 } else {
810 DBG(AVP_DBG_TRACE_XPC_MSG, "%s: msg queued\n", __func__);
811 }
812
813 trpc_put(rinfo->trpc_ep);
814 rinfo_put(rinfo);
815ack:
816 msg_ack_remote(avp, CMD_ACK, 0);
817no_ack:
818 return ret;
819}
820
821static void process_avp_message(struct work_struct *work)
822{
823 struct tegra_avp_info *avp = container_of(work, struct tegra_avp_info,
824 recv_work);
825 struct msg_data *msg = avp->msg_from_avp;
826
827 mutex_lock(&avp->from_avp_lock);
828 rmb();
829 switch (msg->cmd) {
830 case CMD_CONNECT:
831 process_connect_locked(avp, msg);
832 break;
833 case CMD_DISCONNECT:
834 process_disconnect_locked(avp, msg);
835 break;
836 case CMD_MESSAGE:
837 process_message(avp, msg, GFP_KERNEL);
838 break;
839 default:
840 pr_err("%s: unknown cmd (%x) received\n", __func__, msg->cmd);
841 break;
842 }
843 mutex_unlock(&avp->from_avp_lock);
844}
845
846static irqreturn_t avp_mbox_pending_isr(int irq, void *data)
847{
848 struct tegra_avp_info *avp = data;
849 struct msg_data *msg = avp->msg_from_avp;
850 u32 mbox_msg;
851 unsigned long flags;
852 int ret;
853
854 mbox_msg = mbox_readl(MBOX_FROM_AVP);
855 mbox_writel(0, MBOX_FROM_AVP);
856
857 DBG(AVP_DBG_TRACE_XPC_IRQ, "%s: got msg %x\n", __func__, mbox_msg);
858
859 /* XXX: re-use previous message? */
860 if (!(mbox_msg & MBOX_MSG_VALID)) {
861 WARN_ON(1);
862 goto done;
863 }
864
865 mbox_msg <<= 4;
866 if (mbox_msg == 0x2f00bad0UL) {
867 pr_info("%s: petting watchdog\n", __func__);
868 goto done;
869 }
870
871 spin_lock_irqsave(&avp->state_lock, flags);
872 if (avp->shutdown) {
873 spin_unlock_irqrestore(&avp->state_lock, flags);
874 goto done;
875 } else if (avp->defer_remote) {
876 spin_unlock_irqrestore(&avp->state_lock, flags);
877 goto defer;
878 }
879 spin_unlock_irqrestore(&avp->state_lock, flags);
880
881 rmb();
882 if (msg->cmd == CMD_MESSAGE) {
883 ret = process_message(avp, msg, GFP_ATOMIC);
884 if (ret != -ENOMEM)
885 goto done;
886 pr_info("%s: deferring message (%d)\n", __func__, ret);
887 }
888defer:
889 queue_work(avp->recv_wq, &avp->recv_work);
890done:
891 return IRQ_HANDLED;
892}
893
894static int avp_reset(struct tegra_avp_info *avp, unsigned long reset_addr)
895{
896 unsigned long stub_code_phys = virt_to_phys(_tegra_avp_boot_stub);
897 dma_addr_t stub_data_phys;
898 unsigned long timeout;
899 int ret = 0;
900
901 writel(FLOW_MODE_STOP, FLOW_CTRL_HALT_COP_EVENTS);
902
903 _tegra_avp_boot_stub_data.map_phys_addr = avp->kernel_phys;
904 _tegra_avp_boot_stub_data.jump_addr = reset_addr;
905 wmb();
906 stub_data_phys = dma_map_single(NULL, &_tegra_avp_boot_stub_data,
907 sizeof(_tegra_avp_boot_stub_data),
908 DMA_TO_DEVICE);
909
910 writel(stub_code_phys, TEGRA_AVP_RESET_VECTOR_ADDR);
911
912 pr_debug("%s: TEGRA_AVP_RESET_VECTOR=%x\n", __func__, readl(TEGRA_AVP_RESET_VECTOR_ADDR));
913 pr_info("%s: Resetting AVP: reset_addr=%lx\n", __func__, reset_addr);
914
915 tegra_periph_reset_assert(avp->cop_clk);
916 udelay(10);
917 tegra_periph_reset_deassert(avp->cop_clk);
918
919 writel(FLOW_MODE_NONE, FLOW_CTRL_HALT_COP_EVENTS);
920
921 /* the AVP firmware will reprogram its reset vector as the kernel
922 * starts, so a dead kernel can be detected by polling this value */
923 timeout = jiffies + msecs_to_jiffies(2000);
924 while (time_before(jiffies, timeout)) {
925 pr_debug("%s: TEGRA_AVP_RESET_VECTOR=%x\n", __func__, readl(TEGRA_AVP_RESET_VECTOR_ADDR));
926 if (readl(TEGRA_AVP_RESET_VECTOR_ADDR) != stub_code_phys)
927 break;
928 cpu_relax();
929 }
930 if (readl(TEGRA_AVP_RESET_VECTOR_ADDR) == stub_code_phys) {
931 pr_err("%s: Timed out waiting for AVP kernel to start\n", __func__);
932 ret = -EINVAL;
933 }
934 pr_debug("%s: TEGRA_AVP_RESET_VECTOR=%x\n", __func__, readl(TEGRA_AVP_RESET_VECTOR_ADDR));
935 WARN_ON(ret);
936 dma_unmap_single(NULL, stub_data_phys,
937 sizeof(_tegra_avp_boot_stub_data),
938 DMA_TO_DEVICE);
939 return ret;
940}
941
942static void avp_halt(struct tegra_avp_info *avp)
943{
944 /* ensure the AVP is halted */
945 writel(FLOW_MODE_STOP, FLOW_CTRL_HALT_COP_EVENTS);
946 tegra_periph_reset_assert(avp->cop_clk);
947
948 /* set up the initial memory areas and mailbox contents */
949 *((u32 *)avp->msg_from_avp) = 0;
950 *((u32 *)avp->msg_to_avp) = 0xfeedf00d;
951 mbox_writel(0, MBOX_FROM_AVP);
952 mbox_writel(0, MBOX_TO_AVP);
953}
954
955/* Note: CPU_PORT server and AVP_PORT client are registered with the avp
956 * node, but are actually meant to be processed on our side (either
957 * by the svc thread for processing remote calls or by the client
958 * of the char dev for receiving replies for managing remote
959 * libraries/modules. */
960
961static int avp_init(struct tegra_avp_info *avp)
962{
963 const struct firmware *avp_fw;
964 int ret;
965 struct trpc_endpoint *ep;
966 char fw_file[30];
967
968 avp->nvmap_libs = nvmap_create_client(nvmap_dev, "avp_libs");
969 if (IS_ERR_OR_NULL(avp->nvmap_libs)) {
970 pr_err("%s: cannot create libs nvmap client\n", __func__);
971 ret = PTR_ERR(avp->nvmap_libs);
972 goto err_nvmap_create_libs_client;
973 }
974
975 /* put the address of the shared mem area into the mailbox for AVP
976 * to read out when its kernel boots. */
977 mbox_writel(avp->msg, MBOX_TO_AVP);
978
979#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU) /* Tegra2 with AVP MMU */
980 /* paddr is any address returned from nvmap_pin */
981 /* vaddr is AVP_KERNEL_VIRT_BASE */
982 pr_info("%s: Using AVP MMU to relocate AVP kernel\n", __func__);
983 sprintf(fw_file, "nvrm_avp.bin");
984 avp->reset_addr = AVP_KERNEL_VIRT_BASE;
985#elif defined(CONFIG_TEGRA_AVP_KERNEL_ON_SMMU) /* Tegra3 with SMMU */
986 /* paddr is any address behind SMMU */
987 /* vaddr is TEGRA_SMMU_BASE */
988 pr_info("%s: Using SMMU at %lx to load AVP kernel\n",
989 __func__, (unsigned long)avp->kernel_phys);
990 BUG_ON(avp->kernel_phys != 0xeff00000
991 && avp->kernel_phys != 0x0ff00000);
992 sprintf(fw_file, "nvrm_avp_%08lx.bin", (unsigned long)avp->kernel_phys);
993 avp->reset_addr = avp->kernel_phys;
994#else /* nvmem= carveout */
995 /* paddr is found in nvmem= carveout */
996 /* vaddr is same as paddr */
997 /* Find nvmem carveout */
998 if (!pfn_valid(__phys_to_pfn(0x8e000000))) {
999 avp->kernel_phys = 0x8e000000;
1000 }
1001 else if (!pfn_valid(__phys_to_pfn(0x9e000000))) {
1002 avp->kernel_phys = 0x9e000000;
1003 }
1004 else if (!pfn_valid(__phys_to_pfn(0xbe000000))) {
1005 avp->kernel_phys = 0xbe000000;
1006 }
1007 else {
1008 pr_err("Cannot find nvmem= carveout to load AVP kernel\n");
1009 pr_err("Check kernel command line "
1010 "to see if nvmem= is defined\n");
1011 BUG();
1012 }
1013 pr_info("%s: Using nvmem= carveout at %lx to load AVP kernel\n",
1014 __func__, (unsigned long)avp->kernel_phys);
1015 sprintf(fw_file, "nvrm_avp_%08lx.bin", (unsigned long)avp->kernel_phys);
1016 avp->reset_addr = avp->kernel_phys;
1017 avp->kernel_data = ioremap(avp->kernel_phys, SZ_1M);
1018#endif
1019
1020 ret = request_firmware(&avp_fw, fw_file, avp->misc_dev.this_device);
1021 if (ret) {
1022 pr_err("%s: Cannot read firmware '%s'\n", __func__, fw_file);
1023 goto err_req_fw;
1024 }
1025 pr_info("%s: Reading firmware from '%s' (%d bytes)\n", __func__,
1026 fw_file, avp_fw->size);
1027
1028 pr_info("%s: Loading AVP kernel at vaddr=%p paddr=%lx\n",
1029 __func__, avp->kernel_data, (unsigned long)avp->kernel_phys);
1030 memcpy(avp->kernel_data, avp_fw->data, avp_fw->size);
1031 memset(avp->kernel_data + avp_fw->size, 0, SZ_1M - avp_fw->size);
1032
1033 wmb();
1034 release_firmware(avp_fw);
1035
1036 tegra_init_legacy_irq_cop();
1037
1038 ret = avp_reset(avp, avp->reset_addr);
1039 if (ret) {
1040 pr_err("%s: cannot reset the AVP.. aborting..\n", __func__);
1041 goto err_reset;
1042 }
1043
1044 enable_irq(avp->mbox_from_avp_pend_irq);
1045 /* Initialize the avp_svc *first*. This creates RPC_CPU_PORT to be
1046 * ready for remote commands. Then, connect to the
1047 * remote RPC_AVP_PORT to be able to send library load/unload and
1048 * suspend commands to it */
1049 ret = avp_svc_start(avp->avp_svc);
1050 if (ret)
1051 goto err_avp_svc_start;
1052
1053 ep = trpc_create_connect(avp->rpc_node, "RPC_AVP_PORT", NULL,
1054 NULL, -1);
1055 if (IS_ERR(ep)) {
1056 pr_err("%s: can't connect to RPC_AVP_PORT server\n", __func__);
1057 ret = PTR_ERR(ep);
1058 goto err_rpc_avp_port;
1059 }
1060 avp->avp_ep = ep;
1061
1062 avp->initialized = true;
1063 smp_wmb();
1064 pr_info("%s: avp init done\n", __func__);
1065 return 0;
1066
1067err_rpc_avp_port:
1068 avp_svc_stop(avp->avp_svc);
1069err_avp_svc_start:
1070 disable_irq(avp->mbox_from_avp_pend_irq);
1071err_reset:
1072 avp_halt(avp);
1073err_req_fw:
1074 nvmap_client_put(avp->nvmap_libs);
1075err_nvmap_create_libs_client:
1076 avp->nvmap_libs = NULL;
1077 return ret;
1078}
1079
1080static void avp_uninit(struct tegra_avp_info *avp)
1081{
1082 unsigned long flags;
1083 struct rb_node *n;
1084 struct remote_info *rinfo;
1085
1086 spin_lock_irqsave(&avp->state_lock, flags);
1087 avp->initialized = false;
1088 avp->shutdown = true;
1089 spin_unlock_irqrestore(&avp->state_lock, flags);
1090
1091 disable_irq(avp->mbox_from_avp_pend_irq);
1092 cancel_work_sync(&avp->recv_work);
1093
1094 avp_halt(avp);
1095
1096 spin_lock_irqsave(&avp->state_lock, flags);
1097 while ((n = rb_first(&avp->endpoints)) != NULL) {
1098 rinfo = rb_entry(n, struct remote_info, rb_node);
1099 rinfo_get(rinfo);
1100 remote_remove(avp, rinfo);
1101 spin_unlock_irqrestore(&avp->state_lock, flags);
1102
1103 remote_close(rinfo);
1104 rinfo_put(rinfo);
1105
1106 spin_lock_irqsave(&avp->state_lock, flags);
1107 }
1108 spin_unlock_irqrestore(&avp->state_lock, flags);
1109
1110 avp_svc_stop(avp->avp_svc);
1111
1112 if (avp->avp_ep) {
1113 trpc_close(avp->avp_ep);
1114 avp->avp_ep = NULL;
1115 }
1116
1117 libs_cleanup(avp);
1118
1119 avp->shutdown = false;
1120 smp_wmb();
1121 pr_info("%s: avp teardown done\n", __func__);
1122}
1123
1124/* returns the remote lib handle in lib->handle */
1125static int _load_lib(struct tegra_avp_info *avp, struct tegra_avp_lib *lib,
1126 bool from_user)
1127{
1128 struct svc_lib_attach svc;
1129 struct svc_lib_attach_resp resp;
1130 const struct firmware *fw;
1131 void *args;
1132 struct nvmap_handle_ref *lib_handle;
1133 void *lib_data;
1134 phys_addr_t lib_phys;
1135 int ret;
1136
1137 DBG(AVP_DBG_TRACE_LIB, "avp_lib: loading library '%s'\n", lib->name);
1138
1139 args = kmalloc(lib->args_len, GFP_KERNEL);
1140 if (!args) {
1141 pr_err("avp_lib: can't alloc mem for args (%d)\n",
1142 lib->args_len);
1143 return -ENOMEM;
1144 }
1145
1146 if (!from_user)
1147 memcpy(args, lib->args, lib->args_len);
1148 else if (copy_from_user(args, lib->args, lib->args_len)) {
1149 pr_err("avp_lib: can't copy lib args\n");
1150 ret = -EFAULT;
1151 goto err_cp_args;
1152 }
1153
1154 ret = request_firmware(&fw, lib->name, avp->misc_dev.this_device);
1155 if (ret) {
1156 pr_err("avp_lib: Cannot read firmware '%s'\n", lib->name);
1157 goto err_req_fw;
1158 }
1159
1160 lib_handle = nvmap_alloc(avp->nvmap_libs, fw->size, L1_CACHE_BYTES,
1161 NVMAP_HANDLE_UNCACHEABLE, 0);
1162 if (IS_ERR_OR_NULL(lib_handle)) {
1163 pr_err("avp_lib: can't nvmap alloc for lib '%s'\n", lib->name);
1164 ret = PTR_ERR(lib_handle);
1165 goto err_nvmap_alloc;
1166 }
1167
1168 lib_data = nvmap_mmap(lib_handle);
1169 if (!lib_data) {
1170 pr_err("avp_lib: can't nvmap map for lib '%s'\n", lib->name);
1171 ret = -ENOMEM;
1172 goto err_nvmap_mmap;
1173 }
1174
1175 lib_phys = nvmap_pin(avp->nvmap_libs, lib_handle);
1176 if (IS_ERR_VALUE(lib_phys)) {
1177 pr_err("avp_lib: can't nvmap pin for lib '%s'\n", lib->name);
1178 ret = lib_phys;
1179 goto err_nvmap_pin;
1180 }
1181
1182 memcpy(lib_data, fw->data, fw->size);
1183
1184 svc.svc_id = SVC_LIBRARY_ATTACH;
1185 svc.address = lib_phys;
1186 svc.args_len = lib->args_len;
1187 svc.lib_size = fw->size;
1188 svc.reason = lib->greedy ? AVP_LIB_REASON_ATTACH_GREEDY :
1189 AVP_LIB_REASON_ATTACH;
1190 memcpy(svc.args, args, lib->args_len);
1191 wmb();
1192
1193 /* send message, wait for reply */
1194 ret = trpc_send_msg(avp->rpc_node, avp->avp_ep, &svc, sizeof(svc),
1195 GFP_KERNEL);
1196 if (ret)
1197 goto err_send_msg;
1198
1199 ret = trpc_recv_msg(avp->rpc_node, avp->avp_ep, &resp,
1200 sizeof(resp), -1);
1201 if (ret != sizeof(resp)) {
1202 pr_err("avp_lib: Couldn't get lib load reply (%d)\n", ret);
1203 goto err_recv_msg;
1204 } else if (resp.err) {
1205 pr_err("avp_lib: got remote error (%d) while loading lib %s\n",
1206 resp.err, lib->name);
1207 ret = -EPROTO;
1208 goto err_recv_msg;
1209 }
1210 lib->handle = resp.lib_id;
1211 ret = 0;
1212 DBG(AVP_DBG_TRACE_LIB,
1213 "avp_lib: Successfully loaded library %s (lib_id=%x)\n",
1214 lib->name, resp.lib_id);
1215
1216 /* We free the memory here because by this point the AVP has already
1217 * requested memory for the library for all the sections since it does
1218 * it's own relocation and memory management. So, our allocations were
1219 * temporary to hand the library code over to the AVP.
1220 */
1221
1222err_recv_msg:
1223err_send_msg:
1224 nvmap_unpin(avp->nvmap_libs, lib_handle);
1225err_nvmap_pin:
1226 nvmap_munmap(lib_handle, lib_data);
1227err_nvmap_mmap:
1228 nvmap_free(avp->nvmap_libs, lib_handle);
1229err_nvmap_alloc:
1230 release_firmware(fw);
1231err_req_fw:
1232err_cp_args:
1233 kfree(args);
1234 return ret;
1235}
1236
1237static int send_unload_lib_msg(struct tegra_avp_info *avp, u32 handle,
1238 const char *name)
1239{
1240 struct svc_lib_detach svc;
1241 struct svc_lib_detach_resp resp;
1242 int ret;
1243
1244 svc.svc_id = SVC_LIBRARY_DETACH;
1245 svc.reason = AVP_LIB_REASON_DETACH;
1246 svc.lib_id = handle;
1247
1248 ret = trpc_send_msg(avp->rpc_node, avp->avp_ep, &svc, sizeof(svc),
1249 GFP_KERNEL);
1250 if (ret) {
1251 pr_err("avp_lib: can't send unload message to avp for '%s'\n",
1252 name);
1253 goto err;
1254 }
1255
1256 /* Give it a few extra moments to unload. */
1257 msleep(20);
1258
1259 ret = trpc_recv_msg(avp->rpc_node, avp->avp_ep, &resp,
1260 sizeof(resp), -1);
1261 if (ret != sizeof(resp)) {
1262 pr_err("avp_lib: Couldn't get unload reply for '%s' (%d)\n",
1263 name, ret);
1264 } else if (resp.err) {
1265 pr_err("avp_lib: remote error (%d) while unloading lib %s\n",
1266 resp.err, name);
1267 ret = -EPROTO;
1268 } else {
1269 pr_info("avp_lib: Successfully unloaded '%s'\n",
1270 name);
1271 ret = 0;
1272 }
1273
1274err:
1275 return ret;
1276}
1277
1278static struct lib_item *_find_lib_locked(struct tegra_avp_info *avp, u32 handle)
1279{
1280 struct lib_item *item;
1281
1282 list_for_each_entry(item, &avp->libs, list) {
1283 if (item->handle == handle)
1284 return item;
1285 }
1286 return NULL;
1287}
1288
1289static int _insert_lib_locked(struct tegra_avp_info *avp, u32 handle,
1290 char *name)
1291{
1292 struct lib_item *item;
1293
1294 item = kzalloc(sizeof(struct lib_item), GFP_KERNEL);
1295 if (!item)
1296 return -ENOMEM;
1297 item->handle = handle;
1298 strlcpy(item->name, name, TEGRA_AVP_LIB_MAX_NAME);
1299 list_add_tail(&item->list, &avp->libs);
1300 return 0;
1301}
1302
1303static void _delete_lib_locked(struct tegra_avp_info *avp,
1304 struct lib_item *item)
1305{
1306 list_del(&item->list);
1307 kfree(item);
1308}
1309
1310static int handle_load_lib_ioctl(struct tegra_avp_info *avp, unsigned long arg)
1311{
1312 struct tegra_avp_lib lib;
1313 int ret;
1314
1315 pr_debug("%s: ioctl\n", __func__);
1316 if (copy_from_user(&lib, (void __user *)arg, sizeof(lib)))
1317 return -EFAULT;
1318 lib.name[TEGRA_AVP_LIB_MAX_NAME - 1] = '\0';
1319
1320 if (lib.args_len > TEGRA_AVP_LIB_MAX_ARGS) {
1321 pr_err("%s: library args too long (%d)\n", __func__,
1322 lib.args_len);
1323 return -E2BIG;
1324 }
1325
1326 mutex_lock(&avp->libs_lock);
1327 ret = _load_lib(avp, &lib, true);
1328 if (ret)
1329 goto err_load_lib;
1330
1331 if (copy_to_user((void __user *)arg, &lib, sizeof(lib))) {
1332 /* TODO: probably need to free the library from remote
1333 * we just loaded */
1334 ret = -EFAULT;
1335 goto err_copy_to_user;
1336 }
1337 ret = _insert_lib_locked(avp, lib.handle, lib.name);
1338 if (ret) {
1339 pr_err("%s: can't insert lib (%d)\n", __func__, ret);
1340 goto err_insert_lib;
1341 }
1342
1343 mutex_unlock(&avp->libs_lock);
1344 return 0;
1345
1346err_insert_lib:
1347err_copy_to_user:
1348 send_unload_lib_msg(avp, lib.handle, lib.name);
1349err_load_lib:
1350 mutex_unlock(&avp->libs_lock);
1351 return ret;
1352}
1353
1354static void libs_cleanup(struct tegra_avp_info *avp)
1355{
1356 struct lib_item *lib;
1357 struct lib_item *lib_tmp;
1358
1359 mutex_lock(&avp->libs_lock);
1360 list_for_each_entry_safe(lib, lib_tmp, &avp->libs, list) {
1361 _delete_lib_locked(avp, lib);
1362 }
1363
1364 nvmap_client_put(avp->nvmap_libs);
1365 avp->nvmap_libs = NULL;
1366 mutex_unlock(&avp->libs_lock);
1367}
1368
1369static long tegra_avp_ioctl(struct file *file, unsigned int cmd,
1370 unsigned long arg)
1371{
1372 struct tegra_avp_info *avp = tegra_avp;
1373 int ret;
1374
1375 if (_IOC_TYPE(cmd) != TEGRA_AVP_IOCTL_MAGIC ||
1376 _IOC_NR(cmd) < TEGRA_AVP_IOCTL_MIN_NR ||
1377 _IOC_NR(cmd) > TEGRA_AVP_IOCTL_MAX_NR)
1378 return -ENOTTY;
1379
1380 switch (cmd) {
1381 case TEGRA_AVP_IOCTL_LOAD_LIB:
1382 ret = handle_load_lib_ioctl(avp, arg);
1383 break;
1384 case TEGRA_AVP_IOCTL_UNLOAD_LIB:
1385 ret = tegra_avp_unload_lib(avp, arg);
1386 break;
1387 default:
1388 pr_err("avp_lib: Unknown tegra_avp ioctl 0x%x\n", _IOC_NR(cmd));
1389 ret = -ENOTTY;
1390 break;
1391 }
1392 return ret;
1393}
1394
1395int tegra_avp_open(struct tegra_avp_info **avp)
1396{
1397 struct tegra_avp_info *new_avp = tegra_avp;
1398 int ret = 0;
1399
1400 pr_debug("%s: open\n", __func__);
1401 mutex_lock(&new_avp->open_lock);
1402
1403 if (!new_avp->refcount)
1404 ret = avp_init(new_avp);
1405
1406 if (ret < 0) {
1407 mutex_unlock(&new_avp->open_lock);
1408 new_avp = 0;
1409 goto out;
1410 }
1411
1412 new_avp->refcount++;
1413
1414 mutex_unlock(&new_avp->open_lock);
1415out:
1416 *avp = new_avp;
1417 return ret;
1418}
1419
1420static int tegra_avp_open_fops(struct inode *inode, struct file *file)
1421{
1422 struct tegra_avp_info *avp;
1423
1424 nonseekable_open(inode, file);
1425 return tegra_avp_open(&avp);
1426}
1427
1428int tegra_avp_release(struct tegra_avp_info *avp)
1429{
1430 int ret = 0;
1431
1432 pr_debug("%s: close\n", __func__);
1433 mutex_lock(&avp->open_lock);
1434 if (!avp->refcount) {
1435 pr_err("%s: releasing while in invalid state\n", __func__);
1436 ret = -EINVAL;
1437 goto out;
1438 }
1439 if (avp->refcount > 0)
1440 avp->refcount--;
1441 if (!avp->refcount)
1442 avp_uninit(avp);
1443
1444out:
1445 mutex_unlock(&avp->open_lock);
1446 return ret;
1447}
1448
1449static int tegra_avp_release_fops(struct inode *inode, struct file *file)
1450{
1451 struct tegra_avp_info *avp = tegra_avp;
1452 return tegra_avp_release(avp);
1453}
1454
1455static int avp_enter_lp0(struct tegra_avp_info *avp)
1456{
1457 volatile u32 *avp_suspend_done = avp->iram_backup_data
1458 + TEGRA_IRAM_SIZE - TEGRA_RESET_HANDLER_SIZE;
1459 struct svc_enter_lp0 svc;
1460 unsigned long endtime;
1461 int ret;
1462
1463 svc.svc_id = SVC_ENTER_LP0;
1464 svc.src_addr = (u32)TEGRA_IRAM_BASE + TEGRA_RESET_HANDLER_SIZE;
1465 svc.buf_addr = (u32)avp->iram_backup_phys;
1466 svc.buf_size = TEGRA_IRAM_SIZE - TEGRA_RESET_HANDLER_SIZE;
1467
1468 *avp_suspend_done = 0;
1469 wmb();
1470
1471 ret = trpc_send_msg(avp->rpc_node, avp->avp_ep, &svc, sizeof(svc),
1472 GFP_KERNEL);
1473 if (ret) {
1474 pr_err("%s: cannot send AVP suspend message\n", __func__);
1475 return ret;
1476 }
1477
1478 endtime = jiffies + msecs_to_jiffies(1000);
1479 rmb();
1480 while ((*avp_suspend_done == 0) && time_before(jiffies, endtime)) {
1481 udelay(10);
1482 rmb();
1483 }
1484
1485 rmb();
1486 if (*avp_suspend_done == 0) {
1487 pr_err("%s: AVP failed to suspend\n", __func__);
1488 ret = -ETIMEDOUT;
1489 goto err;
1490 }
1491
1492 return 0;
1493
1494err:
1495 return ret;
1496}
1497
1498static int tegra_avp_suspend(struct platform_device *pdev, pm_message_t state)
1499{
1500 struct tegra_avp_info *avp = tegra_avp;
1501 unsigned long flags;
1502 int ret;
1503
1504 pr_info("%s()+\n", __func__);
1505 spin_lock_irqsave(&avp->state_lock, flags);
1506 if (!avp->initialized) {
1507 spin_unlock_irqrestore(&avp->state_lock, flags);
1508 return 0;
1509 }
1510 avp->suspending = true;
1511 spin_unlock_irqrestore(&avp->state_lock, flags);
1512
1513 ret = avp_enter_lp0(avp);
1514 if (ret)
1515 goto err;
1516
1517 avp->resume_addr = readl(TEGRA_AVP_RESUME_ADDR);
1518 if (!avp->resume_addr) {
1519 pr_err("%s: AVP failed to set it's resume address\n", __func__);
1520 ret = -EINVAL;
1521 goto err;
1522 }
1523
1524 disable_irq(avp->mbox_from_avp_pend_irq);
1525
1526 pr_info("avp_suspend: resume_addr=%lx\n", avp->resume_addr);
1527 avp->resume_addr &= 0xfffffffeUL;
1528 pr_info("%s()-\n", __func__);
1529
1530 return 0;
1531
1532err:
1533 /* TODO: we need to kill the AVP so that when we come back
1534 * it could be reinitialized.. We'd probably need to kill
1535 * the users of it so they don't have the wrong state.
1536 */
1537 return ret;
1538}
1539
1540static int tegra_avp_resume(struct platform_device *pdev)
1541{
1542 struct tegra_avp_info *avp = tegra_avp;
1543 int ret = 0;
1544
1545 pr_info("%s()+\n", __func__);
1546 smp_rmb();
1547 if (!avp->initialized)
1548 goto out;
1549
1550 BUG_ON(!avp->resume_addr);
1551
1552 avp_reset(avp, avp->resume_addr);
1553 avp->resume_addr = 0;
1554 avp->suspending = false;
1555 smp_wmb();
1556 enable_irq(avp->mbox_from_avp_pend_irq);
1557
1558 pr_info("%s()-\n", __func__);
1559
1560out:
1561 return ret;
1562}
1563
1564static const struct file_operations tegra_avp_fops = {
1565 .owner = THIS_MODULE,
1566 .open = tegra_avp_open_fops,
1567 .release = tegra_avp_release_fops,
1568 .unlocked_ioctl = tegra_avp_ioctl,
1569};
1570
1571static struct trpc_node avp_trpc_node = {
1572 .name = "avp-remote",
1573 .type = TRPC_NODE_REMOTE,
1574 .try_connect = avp_node_try_connect,
1575};
1576
1577static int tegra_avp_probe(struct platform_device *pdev)
1578{
1579 void *msg_area;
1580 struct tegra_avp_info *avp;
1581 int ret = 0;
1582 int irq;
1583 unsigned int heap_mask;
1584
1585 irq = platform_get_irq_byname(pdev, "mbox_from_avp_pending");
1586 if (irq < 0) {
1587 pr_err("%s: invalid platform data\n", __func__);
1588 return -EINVAL;
1589 }
1590
1591 avp = kzalloc(sizeof(struct tegra_avp_info), GFP_KERNEL);
1592 if (!avp) {
1593 pr_err("%s: cannot allocate tegra_avp_info\n", __func__);
1594 return -ENOMEM;
1595 }
1596
1597 avp->nvmap_drv = nvmap_create_client(nvmap_dev, "avp_core");
1598 if (IS_ERR_OR_NULL(avp->nvmap_drv)) {
1599 pr_err("%s: cannot create drv nvmap client\n", __func__);
1600 ret = PTR_ERR(avp->nvmap_drv);
1601 goto err_nvmap_create_drv_client;
1602 }
1603
1604#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU) /* Tegra2 with AVP MMU */
1605 heap_mask = NVMAP_HEAP_CARVEOUT_GENERIC;
1606#elif defined(CONFIG_TEGRA_AVP_KERNEL_ON_SMMU) /* Tegra3 with SMMU */
1607 heap_mask = NVMAP_HEAP_IOVMM;
1608#else /* nvmem= carveout */
1609 heap_mask = 0;
1610#endif
1611
1612 if (heap_mask == NVMAP_HEAP_IOVMM) {
1613 int i;
1614 /* Tegra3 A01 has different SMMU address in 0xe00000000- */
1615 u32 iovmm_addr[] = {0x0ff00000, 0xeff00000};
1616
1617 for (i = 0; i < ARRAY_SIZE(iovmm_addr); i++) {
1618 avp->kernel_handle = nvmap_alloc_iovm(avp->nvmap_drv,
1619 SZ_1M, L1_CACHE_BYTES,
1620 NVMAP_HANDLE_WRITE_COMBINE,
1621 iovmm_addr[i]);
1622 if (!IS_ERR_OR_NULL(avp->kernel_handle))
1623 break;
1624 }
1625 if (IS_ERR_OR_NULL(avp->kernel_handle)) {
1626 pr_err("%s: cannot create handle\n", __func__);
1627 ret = PTR_ERR(avp->kernel_handle);
1628 goto err_nvmap_alloc;
1629 }
1630
1631 avp->kernel_data = nvmap_mmap(avp->kernel_handle);
1632 if (!avp->kernel_data) {
1633 pr_err("%s: cannot map kernel handle\n", __func__);
1634 ret = -ENOMEM;
1635 goto err_nvmap_mmap;
1636 }
1637
1638 avp->kernel_phys =
1639 nvmap_pin(avp->nvmap_drv, avp->kernel_handle);
1640 if (IS_ERR_VALUE(avp->kernel_phys)) {
1641 pr_err("%s: cannot pin kernel handle\n", __func__);
1642 ret = avp->kernel_phys;
1643 goto err_nvmap_pin;
1644 }
1645
1646 pr_info("%s: allocated IOVM at %lx for AVP kernel\n",
1647 __func__, (unsigned long)avp->kernel_phys);
1648 }
1649
1650 if (heap_mask == NVMAP_HEAP_CARVEOUT_GENERIC) {
1651 avp->kernel_handle = nvmap_alloc(avp->nvmap_drv, SZ_1M, SZ_1M,
1652 NVMAP_HANDLE_UNCACHEABLE, 0);
1653 if (IS_ERR_OR_NULL(avp->kernel_handle)) {
1654 pr_err("%s: cannot create handle\n", __func__);
1655 ret = PTR_ERR(avp->kernel_handle);
1656 goto err_nvmap_alloc;
1657 }
1658
1659 avp->kernel_data = nvmap_mmap(avp->kernel_handle);
1660 if (!avp->kernel_data) {
1661 pr_err("%s: cannot map kernel handle\n", __func__);
1662 ret = -ENOMEM;
1663 goto err_nvmap_mmap;
1664 }
1665
1666 avp->kernel_phys = nvmap_pin(avp->nvmap_drv,
1667 avp->kernel_handle);
1668 if (IS_ERR_VALUE(avp->kernel_phys)) {
1669 pr_err("%s: cannot pin kernel handle\n", __func__);
1670 ret = avp->kernel_phys;
1671 goto err_nvmap_pin;
1672 }
1673
1674 pr_info("%s: allocated carveout memory at %lx for AVP kernel\n",
1675 __func__, (unsigned long)avp->kernel_phys);
1676 }
1677
1678 /* allocate an extra 4 bytes at the end which AVP uses to signal to
1679 * us that it is done suspending.
1680 */
1681 avp->iram_backup_handle =
1682 nvmap_alloc(avp->nvmap_drv, TEGRA_IRAM_SIZE + 4,
1683 L1_CACHE_BYTES, NVMAP_HANDLE_UNCACHEABLE, 0);
1684 if (IS_ERR_OR_NULL(avp->iram_backup_handle)) {
1685 pr_err("%s: cannot create handle for iram backup\n", __func__);
1686 ret = PTR_ERR(avp->iram_backup_handle);
1687 goto err_iram_nvmap_alloc;
1688 }
1689 avp->iram_backup_data = nvmap_mmap(avp->iram_backup_handle);
1690 if (!avp->iram_backup_data) {
1691 pr_err("%s: cannot map iram backup handle\n", __func__);
1692 ret = -ENOMEM;
1693 goto err_iram_nvmap_mmap;
1694 }
1695 avp->iram_backup_phys = nvmap_pin(avp->nvmap_drv,
1696 avp->iram_backup_handle);
1697 if (IS_ERR_VALUE(avp->iram_backup_phys)) {
1698 pr_err("%s: cannot pin iram backup handle\n", __func__);
1699 ret = avp->iram_backup_phys;
1700 goto err_iram_nvmap_pin;
1701 }
1702
1703 avp->mbox_from_avp_pend_irq = irq;
1704 avp->endpoints = RB_ROOT;
1705 spin_lock_init(&avp->state_lock);
1706 mutex_init(&avp->open_lock);
1707 mutex_init(&avp->to_avp_lock);
1708 mutex_init(&avp->from_avp_lock);
1709 INIT_WORK(&avp->recv_work, process_avp_message);
1710
1711 mutex_init(&avp->libs_lock);
1712 INIT_LIST_HEAD(&avp->libs);
1713
1714 avp->recv_wq = alloc_workqueue("avp-msg-recv",
1715 WQ_NON_REENTRANT | WQ_HIGHPRI, 1);
1716 if (!avp->recv_wq) {
1717 pr_err("%s: can't create recve workqueue\n", __func__);
1718 ret = -ENOMEM;
1719 goto err_create_wq;
1720 }
1721
1722 avp->cop_clk = clk_get(&pdev->dev, "cop");
1723 if (IS_ERR_OR_NULL(avp->cop_clk)) {
1724 pr_err("%s: Couldn't get cop clock\n", TEGRA_AVP_NAME);
1725 ret = -ENOENT;
1726 goto err_get_cop_clk;
1727 }
1728
1729 msg_area = dma_alloc_coherent(&pdev->dev, AVP_MSG_AREA_SIZE * 2,
1730 &avp->msg_area_addr, GFP_KERNEL);
1731 if (!msg_area) {
1732 pr_err("%s: cannot allocate msg_area\n", __func__);
1733 ret = -ENOMEM;
1734 goto err_alloc_msg_area;
1735 }
1736 memset(msg_area, 0, AVP_MSG_AREA_SIZE * 2);
1737 avp->msg = ((avp->msg_area_addr >> 4) |
1738 MBOX_MSG_VALID | MBOX_MSG_PENDING_INT_EN);
1739 avp->msg_to_avp = msg_area;
1740 avp->msg_from_avp = msg_area + AVP_MSG_AREA_SIZE;
1741
1742 avp_halt(avp);
1743
1744 avp_trpc_node.priv = avp;
1745 ret = trpc_node_register(&avp_trpc_node);
1746 if (ret) {
1747 pr_err("%s: Can't register avp rpc node\n", __func__);
1748 goto err_node_reg;
1749 }
1750 avp->rpc_node = &avp_trpc_node;
1751
1752 avp->avp_svc = avp_svc_init(pdev, avp->rpc_node);
1753 if (IS_ERR_OR_NULL(avp->avp_svc)) {
1754 pr_err("%s: Cannot initialize avp_svc\n", __func__);
1755 ret = PTR_ERR(avp->avp_svc);
1756 goto err_avp_svc_init;
1757 }
1758
1759 avp->misc_dev.minor = MISC_DYNAMIC_MINOR;
1760 avp->misc_dev.name = "tegra_avp";
1761 avp->misc_dev.fops = &tegra_avp_fops;
1762
1763 ret = misc_register(&avp->misc_dev);
1764 if (ret) {
1765 pr_err("%s: Unable to register misc device!\n", TEGRA_AVP_NAME);
1766 goto err_misc_reg;
1767 }
1768
1769 ret = request_irq(irq, avp_mbox_pending_isr, 0, TEGRA_AVP_NAME, avp);
1770 if (ret) {
1771 pr_err("%s: cannot register irq handler\n", __func__);
1772 goto err_req_irq_pend;
1773 }
1774 disable_irq(avp->mbox_from_avp_pend_irq);
1775
1776 tegra_avp = avp;
1777
1778 pr_info("%s: message area %lx/%lx\n", __func__,
1779 (unsigned long)avp->msg_area_addr,
1780 (unsigned long)avp->msg_area_addr + AVP_MSG_AREA_SIZE);
1781
1782 return 0;
1783
1784err_req_irq_pend:
1785 misc_deregister(&avp->misc_dev);
1786err_misc_reg:
1787 avp_svc_destroy(avp->avp_svc);
1788err_avp_svc_init:
1789 trpc_node_unregister(avp->rpc_node);
1790err_node_reg:
1791 dma_free_coherent(&pdev->dev, AVP_MSG_AREA_SIZE * 2, msg_area,
1792 avp->msg_area_addr);
1793err_alloc_msg_area:
1794 clk_put(avp->cop_clk);
1795err_get_cop_clk:
1796 destroy_workqueue(avp->recv_wq);
1797err_create_wq:
1798 nvmap_unpin(avp->nvmap_drv, avp->iram_backup_handle);
1799err_iram_nvmap_pin:
1800 nvmap_munmap(avp->iram_backup_handle, avp->iram_backup_data);
1801err_iram_nvmap_mmap:
1802 nvmap_free(avp->nvmap_drv, avp->iram_backup_handle);
1803err_iram_nvmap_alloc:
1804 nvmap_unpin(avp->nvmap_drv, avp->kernel_handle);
1805err_nvmap_pin:
1806 nvmap_munmap(avp->kernel_handle, avp->kernel_data);
1807err_nvmap_mmap:
1808 nvmap_free(avp->nvmap_drv, avp->kernel_handle);
1809err_nvmap_alloc:
1810 nvmap_client_put(avp->nvmap_drv);
1811err_nvmap_create_drv_client:
1812 kfree(avp);
1813 tegra_avp = NULL;
1814 return ret;
1815}
1816
1817static int tegra_avp_remove(struct platform_device *pdev)
1818{
1819 struct tegra_avp_info *avp = tegra_avp;
1820
1821 if (!avp)
1822 return 0;
1823
1824 mutex_lock(&avp->open_lock);
1825 /* ensure that noone can open while we tear down */
1826 if (avp->refcount) {
1827 mutex_unlock(&avp->open_lock);
1828 return -EBUSY;
1829 }
1830 mutex_unlock(&avp->open_lock);
1831
1832 misc_deregister(&avp->misc_dev);
1833
1834 avp_halt(avp);
1835
1836 avp_svc_destroy(avp->avp_svc);
1837 trpc_node_unregister(avp->rpc_node);
1838 dma_free_coherent(&pdev->dev, AVP_MSG_AREA_SIZE * 2, avp->msg_to_avp,
1839 avp->msg_area_addr);
1840 clk_put(avp->cop_clk);
1841 destroy_workqueue(avp->recv_wq);
1842 nvmap_unpin(avp->nvmap_drv, avp->iram_backup_handle);
1843 nvmap_munmap(avp->iram_backup_handle, avp->iram_backup_data);
1844 nvmap_free(avp->nvmap_drv, avp->iram_backup_handle);
1845 nvmap_unpin(avp->nvmap_drv, avp->kernel_handle);
1846 nvmap_munmap(avp->kernel_handle, avp->kernel_data);
1847 nvmap_free(avp->nvmap_drv, avp->kernel_handle);
1848 nvmap_client_put(avp->nvmap_drv);
1849 kfree(avp);
1850 tegra_avp = NULL;
1851 return 0;
1852}
1853
1854int tegra_avp_load_lib(struct tegra_avp_info *avp, struct tegra_avp_lib *lib)
1855{
1856 int ret;
1857
1858 if (!avp)
1859 return -ENODEV;
1860
1861 if (!lib)
1862 return -EFAULT;
1863
1864 lib->name[TEGRA_AVP_LIB_MAX_NAME - 1] = '\0';
1865
1866 if (lib->args_len > TEGRA_AVP_LIB_MAX_ARGS) {
1867 pr_err("%s: library args too long (%d)\n", __func__,
1868 lib->args_len);
1869 return -E2BIG;
1870 }
1871
1872 mutex_lock(&avp->libs_lock);
1873 ret = _load_lib(avp, lib, false);
1874 if (ret)
1875 goto err_load_lib;
1876
1877 ret = _insert_lib_locked(avp, lib->handle, lib->name);
1878 if (ret) {
1879 pr_err("%s: can't insert lib (%d)\n", __func__, ret);
1880 goto err_insert_lib;
1881 }
1882
1883 mutex_unlock(&avp->libs_lock);
1884 return 0;
1885
1886err_insert_lib:
1887 ret = send_unload_lib_msg(avp, lib->handle, lib->name);
1888 if (!ret)
1889 DBG(AVP_DBG_TRACE_LIB, "avp_lib: unloaded '%s'\n", lib->name);
1890 else
1891 pr_err("avp_lib: can't unload lib '%s' (%d)\n", lib->name, ret);
1892 lib->handle = 0;
1893err_load_lib:
1894 mutex_unlock(&avp->libs_lock);
1895 return ret;
1896}
1897
1898int tegra_avp_unload_lib(struct tegra_avp_info *avp, unsigned long handle)
1899{
1900 struct lib_item *item;
1901 int ret;
1902
1903 if (!avp)
1904 return -ENODEV;
1905
1906 mutex_lock(&avp->libs_lock);
1907 item = _find_lib_locked(avp, handle);
1908 if (!item) {
1909 pr_err("avp_lib: avp lib with handle 0x%x not found\n",
1910 (u32)handle);
1911 ret = -ENOENT;
1912 goto err_find;
1913 }
1914 ret = send_unload_lib_msg(avp, item->handle, item->name);
1915 if (!ret)
1916 DBG(AVP_DBG_TRACE_LIB, "avp_lib: unloaded '%s'\n", item->name);
1917 else
1918 pr_err("avp_lib: can't unload lib '%s'/0x%x (%d)\n", item->name,
1919 item->handle, ret);
1920 _delete_lib_locked(avp, item);
1921
1922err_find:
1923 mutex_unlock(&avp->libs_lock);
1924 return ret;
1925}
1926
1927static struct platform_driver tegra_avp_driver = {
1928 .probe = tegra_avp_probe,
1929 .remove = tegra_avp_remove,
1930 .suspend = tegra_avp_suspend,
1931 .resume = tegra_avp_resume,
1932 .driver = {
1933 .name = TEGRA_AVP_NAME,
1934 .owner = THIS_MODULE,
1935 },
1936};
1937
1938static int __init tegra_avp_init(void)
1939{
1940 return platform_driver_register(&tegra_avp_driver);
1941}
1942
1943static void __exit tegra_avp_exit(void)
1944{
1945 platform_driver_unregister(&tegra_avp_driver);
1946}
1947
1948module_init(tegra_avp_init);
1949module_exit(tegra_avp_exit);
diff --git a/drivers/media/video/tegra/avp/avp.h b/drivers/media/video/tegra/avp/avp.h
new file mode 100644
index 00000000000..4f2287743a0
--- /dev/null
+++ b/drivers/media/video/tegra/avp/avp.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 * Author: Dima Zavin <dima@android.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#ifndef __MEDIA_VIDEO_TEGRA_AVP_H
17#define __MEDIA_VIDEO_TEGRA_AVP_H
18
19#include <linux/platform_device.h>
20#include <linux/types.h>
21
22#include "trpc.h"
23
24struct avp_svc_info;
25
26struct avp_svc_info *avp_svc_init(struct platform_device *pdev,
27 struct trpc_node *rpc_node);
28void avp_svc_destroy(struct avp_svc_info *avp_svc);
29int avp_svc_start(struct avp_svc_info *svc);
30void avp_svc_stop(struct avp_svc_info *svc);
31
32#endif
diff --git a/drivers/media/video/tegra/avp/avp_msg.h b/drivers/media/video/tegra/avp/avp_msg.h
new file mode 100644
index 00000000000..615d890d544
--- /dev/null
+++ b/drivers/media/video/tegra/avp/avp_msg.h
@@ -0,0 +1,358 @@
1/* drivers/media/video/tegra/avp/avp_msg.h
2 *
3 * Copyright (C) 2010 Google, Inc.
4 * Author: Dima Zavin <dima@android.com>
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef __MEDIA_VIDEO_TEGRA_AVP_MSG_H
18#define __MEDIA_VIDEO_TEGRA_AVP_MSG_H
19
20#include <linux/tegra_avp.h>
21#include <linux/types.h>
22
23/* Note: the port name string is not NUL terminated, so make sure to
24 * allocate appropriate space locally when operating on the string */
25#define XPC_PORT_NAME_LEN 16
26
27#define SVC_ARGS_MAX_LEN 220
28#define SVC_MAX_STRING_LEN 200
29
30#define AVP_ERR_ENOTSUP 0x2
31#define AVP_ERR_EINVAL 0x4
32#define AVP_ERR_ENOMEM 0x6
33#define AVP_ERR_EACCES 0x00030010
34
35enum {
36 SVC_NVMAP_CREATE = 0,
37 SVC_NVMAP_CREATE_RESPONSE = 1,
38 SVC_NVMAP_FREE = 3,
39 SVC_NVMAP_ALLOC = 4,
40 SVC_NVMAP_ALLOC_RESPONSE = 5,
41 SVC_NVMAP_PIN = 6,
42 SVC_NVMAP_PIN_RESPONSE = 7,
43 SVC_NVMAP_UNPIN = 8,
44 SVC_NVMAP_UNPIN_RESPONSE = 9,
45 SVC_NVMAP_GET_ADDRESS = 10,
46 SVC_NVMAP_GET_ADDRESS_RESPONSE = 11,
47 SVC_NVMAP_FROM_ID = 12,
48 SVC_NVMAP_FROM_ID_RESPONSE = 13,
49 SVC_MODULE_CLOCK = 14,
50 SVC_MODULE_CLOCK_RESPONSE = 15,
51 SVC_MODULE_RESET = 16,
52 SVC_MODULE_RESET_RESPONSE = 17,
53 SVC_POWER_REGISTER = 18,
54 SVC_POWER_UNREGISTER = 19,
55 SVC_POWER_STARVATION = 20,
56 SVC_POWER_BUSY_HINT = 21,
57 SVC_POWER_BUSY_HINT_MULTI = 22,
58 SVC_DFS_GETSTATE = 23,
59 SVC_DFS_GETSTATE_RESPONSE = 24,
60 SVC_POWER_RESPONSE = 25,
61 SVC_POWER_MAXFREQ = 26,
62 SVC_ENTER_LP0 = 27,
63 SVC_ENTER_LP0_RESPONSE = 28,
64 SVC_PRINTF = 29,
65 SVC_LIBRARY_ATTACH = 30,
66 SVC_LIBRARY_ATTACH_RESPONSE = 31,
67 SVC_LIBRARY_DETACH = 32,
68 SVC_LIBRARY_DETACH_RESPONSE = 33,
69 SVC_AVP_WDT_RESET = 34,
70 SVC_DFS_GET_CLK_UTIL = 35,
71 SVC_DFS_GET_CLK_UTIL_RESPONSE = 36,
72 SVC_MODULE_CLOCK_SET = 37,
73 SVC_MODULE_CLOCK_SET_RESPONSE = 38,
74 SVC_MODULE_CLOCK_GET = 39,
75 SVC_MODULE_CLOCK_GET_RESPONSE = 40,
76};
77
78struct svc_msg {
79 u32 svc_id;
80 u8 data[0];
81};
82
83struct svc_common_resp {
84 u32 svc_id;
85 u32 err;
86};
87
88struct svc_printf {
89 u32 svc_id;
90 const char str[SVC_MAX_STRING_LEN];
91};
92
93struct svc_enter_lp0 {
94 u32 svc_id;
95 u32 src_addr;
96 u32 buf_addr;
97 u32 buf_size;
98};
99
100/* nvmap messages */
101struct svc_nvmap_create {
102 u32 svc_id;
103 u32 size;
104};
105
106struct svc_nvmap_create_resp {
107 u32 svc_id;
108 u32 handle_id;
109 u32 err;
110};
111
112enum {
113 AVP_NVMAP_HEAP_EXTERNAL = 1,
114 AVP_NVMAP_HEAP_GART = 2,
115 AVP_NVMAP_HEAP_EXTERNAL_CARVEOUT = 3,
116 AVP_NVMAP_HEAP_IRAM = 4,
117};
118
119struct svc_nvmap_alloc {
120 u32 svc_id;
121 u32 handle_id;
122 u32 heaps[4];
123 u32 num_heaps;
124 u32 align;
125 u32 mapping_type;
126};
127
128struct svc_nvmap_free {
129 u32 svc_id;
130 u32 handle_id;
131};
132
133struct svc_nvmap_pin {
134 u32 svc_id;
135 u32 handle_id;
136};
137
138struct svc_nvmap_pin_resp {
139 u32 svc_id;
140 u32 addr;
141};
142
143struct svc_nvmap_unpin {
144 u32 svc_id;
145 u32 handle_id;
146};
147
148struct svc_nvmap_from_id {
149 u32 svc_id;
150 u32 handle_id;
151};
152
153struct svc_nvmap_get_addr {
154 u32 svc_id;
155 u32 handle_id;
156 u32 offs;
157};
158
159struct svc_nvmap_get_addr_resp {
160 u32 svc_id;
161 u32 addr;
162};
163
164/* library management messages */
165enum {
166 AVP_LIB_REASON_ATTACH = 0,
167 AVP_LIB_REASON_DETACH = 1,
168 AVP_LIB_REASON_ATTACH_GREEDY = 2,
169};
170
171struct svc_lib_attach {
172 u32 svc_id;
173 u32 address;
174 u32 args_len;
175 u32 lib_size;
176 u8 args[SVC_ARGS_MAX_LEN];
177 u32 reason;
178};
179
180struct svc_lib_attach_resp {
181 u32 svc_id;
182 u32 err;
183 u32 lib_id;
184};
185
186struct svc_lib_detach {
187 u32 svc_id;
188 u32 reason;
189 u32 lib_id;
190};
191
192struct svc_lib_detach_resp {
193 u32 svc_id;
194 u32 err;
195};
196
197/* hw module management from the AVP side */
198enum {
199 AVP_MODULE_ID_AVP = 2,
200 AVP_MODULE_ID_VCP = 3,
201 AVP_MODULE_ID_BSEA = 27,
202 AVP_MODULE_ID_VDE = 28,
203 AVP_MODULE_ID_MPE = 29,
204};
205
206struct svc_module_ctrl {
207 u32 svc_id;
208 u32 module_id;
209 u32 client_id;
210 u8 enable;
211};
212
213struct svc_clock_ctrl {
214 u32 svc_id;
215 u32 module_id;
216 u32 clk_freq;
217};
218
219struct svc_clock_ctrl_response {
220 u32 svc_id;
221 u32 err;
222 u32 act_freq;
223};
224
225/* power messages */
226struct svc_pwr_register {
227 u32 svc_id;
228 u32 client_id;
229 u32 unused;
230};
231
232struct svc_pwr_register_resp {
233 u32 svc_id;
234 u32 err;
235 u32 client_id;
236};
237
238struct svc_pwr_starve_hint {
239 u32 svc_id;
240 u32 dfs_clk_id;
241 u32 client_id;
242 u8 starving;
243};
244
245struct svc_pwr_busy_hint {
246 u32 svc_id;
247 u32 dfs_clk_id;
248 u32 client_id;
249 u32 boost_ms; /* duration */
250 u32 boost_freq; /* in khz */
251};
252
253struct svc_pwr_max_freq {
254 u32 svc_id;
255 u32 module_id;
256};
257
258struct svc_pwr_max_freq_resp {
259 u32 svc_id;
260 u32 freq;
261};
262
263/* dfs related messages */
264enum {
265 AVP_DFS_STATE_INVALID = 0,
266 AVP_DFS_STATE_DISABLED = 1,
267 AVP_DFS_STATE_STOPPED = 2,
268 AVP_DFS_STATE_CLOSED_LOOP = 3,
269 AVP_DFS_STATE_PROFILED_LOOP = 4,
270};
271
272struct svc_dfs_get_state_resp {
273 u32 svc_id;
274 u32 state;
275};
276
277enum {
278 AVP_DFS_CLK_CPU = 1,
279 AVP_DFS_CLK_AVP = 2,
280 AVP_DFS_CLK_SYSTEM = 3,
281 AVP_DFS_CLK_AHB = 4,
282 AVP_DFS_CLK_APB = 5,
283 AVP_DFS_CLK_VDE = 6,
284 /* external memory controller */
285 AVP_DFS_CLK_EMC = 7,
286};
287
288struct avp_clk_usage {
289 u32 min;
290 u32 max;
291 u32 curr_min;
292 u32 curr_max;
293 u32 curr;
294 u32 avg; /* average activity.. whatever that means */
295};
296
297struct svc_dfs_get_clk_util {
298 u32 svc_id;
299 u32 dfs_clk_id;
300};
301
302/* all units are in kHz */
303struct svc_dfs_get_clk_util_resp {
304 u32 svc_id;
305 u32 err;
306 struct avp_clk_usage usage;
307};
308
309/************************/
310
311enum {
312 CMD_ACK = 0,
313 CMD_CONNECT = 2,
314 CMD_DISCONNECT = 3,
315 CMD_MESSAGE = 4,
316 CMD_RESPONSE = 5,
317};
318
319struct msg_data {
320 u32 cmd;
321 u8 data[0];
322};
323
324struct msg_ack {
325 u32 cmd;
326 u32 arg;
327};
328
329struct msg_connect {
330 u32 cmd;
331 u32 port_id;
332 /* not NUL terminated, just 0 padded */
333 char name[XPC_PORT_NAME_LEN];
334};
335
336struct msg_connect_reply {
337 u32 cmd;
338 u32 port_id;
339};
340
341struct msg_disconnect {
342 u32 cmd;
343 u32 port_id;
344};
345
346struct msg_disconnect_reply {
347 u32 cmd;
348 u32 ack;
349};
350
351struct msg_port_data {
352 u32 cmd;
353 u32 port_id;
354 u32 msg_len;
355 u8 data[0];
356};
357
358#endif
diff --git a/drivers/media/video/tegra/avp/avp_svc.c b/drivers/media/video/tegra/avp/avp_svc.c
new file mode 100644
index 00000000000..17c8b8535a6
--- /dev/null
+++ b/drivers/media/video/tegra/avp/avp_svc.c
@@ -0,0 +1,890 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 * Author: Dima Zavin <dima@android.com>
4 *
5 * Copyright (C) 2010-2011 NVIDIA Corporation
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/clk.h>
19#include <linux/delay.h>
20#include <linux/dma-mapping.h>
21#include <linux/err.h>
22#include <linux/io.h>
23#include <linux/kthread.h>
24#include <linux/list.h>
25#include <linux/mutex.h>
26#include <linux/slab.h>
27#include <linux/tegra_rpc.h>
28#include <linux/tegra_avp.h>
29#include <linux/types.h>
30
31#include <mach/clk.h>
32#include <mach/nvmap.h>
33
34#include "../../../../video/tegra/nvmap/nvmap.h"
35
36#include "avp_msg.h"
37#include "trpc.h"
38#include "avp.h"
39
40enum {
41 AVP_DBG_TRACE_SVC = 1U << 0,
42};
43
44static u32 debug_mask;
45module_param_named(debug_mask, debug_mask, uint, S_IWUSR | S_IRUGO);
46
47#define DBG(flag, args...) \
48 do { if (unlikely(debug_mask & (flag))) pr_info(args); } while (0)
49
50enum {
51 CLK_REQUEST_VCP = 0,
52 CLK_REQUEST_BSEA = 1,
53 CLK_REQUEST_VDE = 2,
54 CLK_REQUEST_AVP = 3,
55 NUM_CLK_REQUESTS,
56};
57
58struct avp_module {
59 const char *name;
60 u32 clk_req;
61};
62
63static struct avp_module avp_modules[] = {
64 [AVP_MODULE_ID_AVP] = {
65 .name = "cop",
66 .clk_req = CLK_REQUEST_AVP,
67 },
68 [AVP_MODULE_ID_VCP] = {
69 .name = "vcp",
70 .clk_req = CLK_REQUEST_VCP,
71 },
72 [AVP_MODULE_ID_BSEA] = {
73 .name = "bsea",
74 .clk_req = CLK_REQUEST_BSEA,
75 },
76 [AVP_MODULE_ID_VDE] = {
77 .name = "vde",
78 .clk_req = CLK_REQUEST_VDE,
79 },
80};
81#define NUM_AVP_MODULES ARRAY_SIZE(avp_modules)
82
83struct avp_clk {
84 struct clk *clk;
85 int refcnt;
86 struct avp_module *mod;
87};
88
89struct avp_svc_info {
90 struct avp_clk clks[NUM_CLK_REQUESTS];
91 /* used for dvfs */
92 struct clk *sclk;
93 struct clk *emcclk;
94
95 struct mutex clk_lock;
96
97 struct trpc_endpoint *cpu_ep;
98 struct task_struct *svc_thread;
99
100 /* client for remote allocations, for easy tear down */
101 struct nvmap_client *nvmap_remote;
102 struct trpc_node *rpc_node;
103 unsigned long max_avp_rate;
104 unsigned long emc_rate;
105
106 /* variable to check if video is present */
107 bool is_vde_on;
108};
109
110static void do_svc_nvmap_create(struct avp_svc_info *avp_svc,
111 struct svc_msg *_msg,
112 size_t len)
113{
114 struct svc_nvmap_create *msg = (struct svc_nvmap_create *)_msg;
115 struct svc_nvmap_create_resp resp;
116 struct nvmap_handle_ref *handle;
117 u32 handle_id = 0;
118 u32 err = 0;
119
120 handle = nvmap_create_handle(avp_svc->nvmap_remote, msg->size);
121 if (unlikely(IS_ERR(handle))) {
122 pr_err("avp_svc: error creating handle (%d bytes) for remote\n",
123 msg->size);
124 err = AVP_ERR_ENOMEM;
125 } else
126 handle_id = (u32)nvmap_ref_to_id(handle);
127
128 resp.svc_id = SVC_NVMAP_CREATE_RESPONSE;
129 resp.err = err;
130 resp.handle_id = handle_id;
131 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
132 sizeof(resp), GFP_KERNEL);
133 /* TODO: do we need to put the handle if send_msg failed? */
134}
135
136static void do_svc_nvmap_alloc(struct avp_svc_info *avp_svc,
137 struct svc_msg *_msg,
138 size_t len)
139{
140 struct svc_nvmap_alloc *msg = (struct svc_nvmap_alloc *)_msg;
141 struct svc_common_resp resp;
142 struct nvmap_handle *handle;
143 u32 err = 0;
144 u32 heap_mask = 0;
145 int i;
146 size_t align;
147
148 handle = nvmap_get_handle_id(avp_svc->nvmap_remote, msg->handle_id);
149 if (IS_ERR(handle)) {
150 pr_err("avp_svc: unknown remote handle 0x%x\n", msg->handle_id);
151 err = AVP_ERR_EACCES;
152 goto out;
153 }
154
155 if (msg->num_heaps > 4) {
156 pr_err("avp_svc: invalid remote alloc request (%d heaps?!)\n",
157 msg->num_heaps);
158 /* TODO: should we error out instead ? */
159 msg->num_heaps = 0;
160 }
161 if (msg->num_heaps == 0)
162 heap_mask = NVMAP_HEAP_CARVEOUT_GENERIC | NVMAP_HEAP_SYSMEM;
163
164 for (i = 0; i < msg->num_heaps; i++) {
165 switch (msg->heaps[i]) {
166 case AVP_NVMAP_HEAP_EXTERNAL:
167 heap_mask |= NVMAP_HEAP_SYSMEM;
168 break;
169 case AVP_NVMAP_HEAP_GART:
170 heap_mask |= NVMAP_HEAP_IOVMM;
171 break;
172 case AVP_NVMAP_HEAP_EXTERNAL_CARVEOUT:
173 heap_mask |= NVMAP_HEAP_CARVEOUT_GENERIC;
174 break;
175 case AVP_NVMAP_HEAP_IRAM:
176 heap_mask |= NVMAP_HEAP_CARVEOUT_IRAM;
177 break;
178 default:
179 break;
180 }
181 }
182
183 align = max_t(size_t, L1_CACHE_BYTES, msg->align);
184 err = nvmap_alloc_handle_id(avp_svc->nvmap_remote, msg->handle_id,
185 heap_mask, align, 0);
186 nvmap_handle_put(handle);
187 if (err) {
188 pr_err("avp_svc: can't allocate for handle 0x%x (%d)\n",
189 msg->handle_id, err);
190 err = AVP_ERR_ENOMEM;
191 }
192
193out:
194 resp.svc_id = SVC_NVMAP_ALLOC_RESPONSE;
195 resp.err = err;
196 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
197 sizeof(resp), GFP_KERNEL);
198}
199
200static void do_svc_nvmap_free(struct avp_svc_info *avp_svc,
201 struct svc_msg *_msg,
202 size_t len)
203{
204 struct svc_nvmap_free *msg = (struct svc_nvmap_free *)_msg;
205
206 nvmap_free_handle_id(avp_svc->nvmap_remote, msg->handle_id);
207}
208
209static void do_svc_nvmap_pin(struct avp_svc_info *avp_svc,
210 struct svc_msg *_msg,
211 size_t len)
212{
213 struct svc_nvmap_pin *msg = (struct svc_nvmap_pin *)_msg;
214 struct svc_nvmap_pin_resp resp;
215 struct nvmap_handle_ref *handle;
216 phys_addr_t addr = ~0UL;
217 unsigned long id = msg->handle_id;
218 int err;
219
220 handle = nvmap_duplicate_handle_id(avp_svc->nvmap_remote, id);
221 if (IS_ERR(handle)) {
222 pr_err("avp_svc: can't dup handle %lx\n", id);
223 goto out;
224 }
225 err = nvmap_pin_ids(avp_svc->nvmap_remote, 1, &id);
226 if (err) {
227 pr_err("avp_svc: can't pin for handle %lx (%d)\n", id, err);
228 goto out;
229 }
230 addr = nvmap_handle_address(avp_svc->nvmap_remote, id);
231
232out:
233 resp.svc_id = SVC_NVMAP_PIN_RESPONSE;
234 resp.addr = addr;
235 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
236 sizeof(resp), GFP_KERNEL);
237}
238
239static void do_svc_nvmap_unpin(struct avp_svc_info *avp_svc,
240 struct svc_msg *_msg,
241 size_t len)
242{
243 struct svc_nvmap_unpin *msg = (struct svc_nvmap_unpin *)_msg;
244 struct svc_common_resp resp;
245 unsigned long id = msg->handle_id;
246
247 nvmap_unpin_ids(avp_svc->nvmap_remote, 1, &id);
248 nvmap_free_handle_id(avp_svc->nvmap_remote, id);
249
250 resp.svc_id = SVC_NVMAP_UNPIN_RESPONSE;
251 resp.err = 0;
252 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
253 sizeof(resp), GFP_KERNEL);
254}
255
256static void do_svc_nvmap_from_id(struct avp_svc_info *avp_svc,
257 struct svc_msg *_msg,
258 size_t len)
259{
260 struct svc_nvmap_from_id *msg = (struct svc_nvmap_from_id *)_msg;
261 struct svc_common_resp resp;
262 struct nvmap_handle_ref *handle;
263 int err = 0;
264
265 handle = nvmap_duplicate_handle_id(avp_svc->nvmap_remote,
266 msg->handle_id);
267 if (IS_ERR(handle)) {
268 pr_err("avp_svc: can't duplicate handle for id 0x%x (%d)\n",
269 msg->handle_id, (int)PTR_ERR(handle));
270 err = AVP_ERR_ENOMEM;
271 }
272
273 resp.svc_id = SVC_NVMAP_FROM_ID_RESPONSE;
274 resp.err = err;
275 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
276 sizeof(resp), GFP_KERNEL);
277}
278
279static void do_svc_nvmap_get_addr(struct avp_svc_info *avp_svc,
280 struct svc_msg *_msg,
281 size_t len)
282{
283 struct svc_nvmap_get_addr *msg = (struct svc_nvmap_get_addr *)_msg;
284 struct svc_nvmap_get_addr_resp resp;
285
286 resp.svc_id = SVC_NVMAP_GET_ADDRESS_RESPONSE;
287 resp.addr = nvmap_handle_address(avp_svc->nvmap_remote, msg->handle_id);
288 resp.addr += msg->offs;
289 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
290 sizeof(resp), GFP_KERNEL);
291}
292
293static void do_svc_pwr_register(struct avp_svc_info *avp_svc,
294 struct svc_msg *_msg,
295 size_t len)
296{
297 struct svc_pwr_register *msg = (struct svc_pwr_register *)_msg;
298 struct svc_pwr_register_resp resp;
299
300 resp.svc_id = SVC_POWER_RESPONSE;
301 resp.err = 0;
302 resp.client_id = msg->client_id;
303
304 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
305 sizeof(resp), GFP_KERNEL);
306}
307
308static struct avp_module *find_avp_module(struct avp_svc_info *avp_svc, u32 id)
309{
310 if (id < NUM_AVP_MODULES && avp_modules[id].name)
311 return &avp_modules[id];
312 return NULL;
313}
314
315static void do_svc_module_reset(struct avp_svc_info *avp_svc,
316 struct svc_msg *_msg,
317 size_t len)
318{
319 struct svc_module_ctrl *msg = (struct svc_module_ctrl *)_msg;
320 struct svc_common_resp resp;
321 struct avp_module *mod;
322 struct avp_clk *aclk;
323
324 mod = find_avp_module(avp_svc, msg->module_id);
325 if (!mod) {
326 if (msg->module_id == AVP_MODULE_ID_AVP)
327 pr_err("avp_svc: AVP suicidal?!?!\n");
328 else
329 pr_err("avp_svc: Unknown module reset requested: %d\n",
330 msg->module_id);
331 /* other side doesn't handle errors for reset */
332 resp.err = 0;
333 goto send_response;
334 }
335
336 aclk = &avp_svc->clks[mod->clk_req];
337 tegra_periph_reset_assert(aclk->clk);
338 udelay(10);
339 tegra_periph_reset_deassert(aclk->clk);
340 resp.err = 0;
341
342send_response:
343 resp.svc_id = SVC_MODULE_RESET_RESPONSE;
344 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
345 sizeof(resp), GFP_KERNEL);
346}
347
348static void do_svc_module_clock(struct avp_svc_info *avp_svc,
349 struct svc_msg *_msg,
350 size_t len)
351{
352 struct svc_module_ctrl *msg = (struct svc_module_ctrl *)_msg;
353 struct svc_common_resp resp;
354 struct avp_module *mod;
355 struct avp_clk *aclk;
356 unsigned long emc_rate = 0;
357
358 mod = find_avp_module(avp_svc, msg->module_id);
359 if (!mod) {
360 pr_err("avp_svc: unknown module clock requested: %d\n",
361 msg->module_id);
362 resp.err = AVP_ERR_EINVAL;
363 goto send_response;
364 }
365
366 if (msg->module_id == AVP_MODULE_ID_VDE)
367 avp_svc->is_vde_on = msg->enable;
368
369 if (avp_svc->is_vde_on == true)
370 emc_rate = ULONG_MAX;
371
372 mutex_lock(&avp_svc->clk_lock);
373 aclk = &avp_svc->clks[mod->clk_req];
374 if (msg->enable) {
375 if (aclk->refcnt++ == 0) {
376 clk_set_rate(avp_svc->emcclk, emc_rate);
377 clk_enable(avp_svc->emcclk);
378 clk_enable(avp_svc->sclk);
379 clk_enable(aclk->clk);
380 }
381 } else {
382 if (unlikely(aclk->refcnt == 0)) {
383 pr_err("avp_svc: unbalanced clock disable for '%s'\n",
384 aclk->mod->name);
385 } else if (--aclk->refcnt == 0) {
386 clk_disable(aclk->clk);
387 clk_set_rate(avp_svc->sclk, 0);
388 clk_disable(avp_svc->sclk);
389 clk_set_rate(avp_svc->emcclk, 0);
390 clk_disable(avp_svc->emcclk);
391 }
392 }
393 mutex_unlock(&avp_svc->clk_lock);
394 resp.err = 0;
395
396send_response:
397 resp.svc_id = SVC_MODULE_CLOCK_RESPONSE;
398 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
399 sizeof(resp), GFP_KERNEL);
400}
401
402static void do_svc_null_response(struct avp_svc_info *avp_svc,
403 struct svc_msg *_msg,
404 size_t len, u32 resp_svc_id)
405{
406 struct svc_common_resp resp;
407 resp.svc_id = resp_svc_id;
408 resp.err = 0;
409 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
410 sizeof(resp), GFP_KERNEL);
411}
412
413static void do_svc_dfs_get_state(struct avp_svc_info *avp_svc,
414 struct svc_msg *_msg,
415 size_t len)
416{
417 struct svc_dfs_get_state_resp resp;
418 resp.svc_id = SVC_DFS_GETSTATE_RESPONSE;
419 resp.state = AVP_DFS_STATE_STOPPED;
420 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
421 sizeof(resp), GFP_KERNEL);
422}
423
424static void do_svc_dfs_get_clk_util(struct avp_svc_info *avp_svc,
425 struct svc_msg *_msg,
426 size_t len)
427{
428 struct svc_dfs_get_clk_util_resp resp;
429
430 resp.svc_id = SVC_DFS_GET_CLK_UTIL_RESPONSE;
431 resp.err = 0;
432 memset(&resp.usage, 0, sizeof(struct avp_clk_usage));
433 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
434 sizeof(resp), GFP_KERNEL);
435}
436
437static void do_svc_pwr_max_freq(struct avp_svc_info *avp_svc,
438 struct svc_msg *_msg,
439 size_t len)
440{
441 struct svc_pwr_max_freq_resp resp;
442
443 resp.svc_id = SVC_POWER_MAXFREQ;
444 resp.freq = 0;
445 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
446 sizeof(resp), GFP_KERNEL);
447}
448
449static void do_svc_printf(struct avp_svc_info *avp_svc, struct svc_msg *_msg,
450 size_t len)
451{
452 struct svc_printf *msg = (struct svc_printf *)_msg;
453 char tmp_str[SVC_MAX_STRING_LEN];
454
455 /* ensure we null terminate the source */
456 strlcpy(tmp_str, msg->str, SVC_MAX_STRING_LEN);
457 pr_info("[AVP]: %s", tmp_str);
458}
459
460static void do_svc_module_clock_set(struct avp_svc_info *avp_svc,
461 struct svc_msg *_msg,
462 size_t len)
463{
464 struct svc_clock_ctrl *msg = (struct svc_clock_ctrl *)_msg;
465 struct svc_clock_ctrl_response resp;
466 struct avp_module *mod;
467 struct avp_clk *aclk;
468 int ret = 0;
469
470 mod = find_avp_module(avp_svc, msg->module_id);
471 if (!mod) {
472 pr_err("avp_svc: unknown module clock requested: %d\n",
473 msg->module_id);
474 resp.err = AVP_ERR_EINVAL;
475 goto send_response;
476 }
477
478 mutex_lock(&avp_svc->clk_lock);
479 if (msg->module_id == AVP_MODULE_ID_AVP) {
480 /* check if max avp clock is asked and set max emc frequency */
481 if (msg->clk_freq >= avp_svc->max_avp_rate) {
482 clk_set_rate(avp_svc->emcclk, ULONG_MAX);
483 }
484 else {
485 /* if no, set emc frequency as per platform data.
486 * if no platform data is send, set it to maximum */
487 if (avp_svc->emc_rate)
488 clk_set_rate(avp_svc->emcclk, avp_svc->emc_rate);
489 else
490 clk_set_rate(avp_svc->emcclk, ULONG_MAX);
491 }
492 ret = clk_set_rate(avp_svc->sclk, msg->clk_freq);
493 } else {
494 aclk = &avp_svc->clks[mod->clk_req];
495 ret = clk_set_rate(aclk->clk, msg->clk_freq);
496 }
497 if (ret) {
498 pr_err("avp_svc: Failed to set module (id = %d) frequency to %d Hz\n",
499 msg->module_id, msg->clk_freq);
500 resp.err = AVP_ERR_EINVAL;
501 resp.act_freq = 0;
502 mutex_unlock(&avp_svc->clk_lock);
503 goto send_response;
504 }
505
506 if (msg->module_id == AVP_MODULE_ID_AVP)
507 resp.act_freq = clk_get_rate(avp_svc->sclk);
508 else
509 resp.act_freq = clk_get_rate(aclk->clk);
510
511 mutex_unlock(&avp_svc->clk_lock);
512 resp.err = 0;
513
514send_response:
515 resp.svc_id = SVC_MODULE_CLOCK_SET_RESPONSE;
516 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
517 sizeof(resp), GFP_KERNEL);
518}
519
520static void do_svc_unsupported_msg(struct avp_svc_info *avp_svc,
521 u32 resp_svc_id)
522{
523 struct svc_common_resp resp;
524
525 resp.err = AVP_ERR_ENOTSUP;
526 resp.svc_id = resp_svc_id;
527 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
528 sizeof(resp), GFP_KERNEL);
529}
530
531static void do_svc_module_clock_get(struct avp_svc_info *avp_svc,
532 struct svc_msg *_msg,
533 size_t len)
534{
535 struct svc_clock_ctrl *msg = (struct svc_clock_ctrl *)_msg;
536 struct svc_clock_ctrl_response resp;
537 struct avp_module *mod;
538 struct avp_clk *aclk;
539
540 mod = find_avp_module(avp_svc, msg->module_id);
541 if (!mod) {
542 pr_err("avp_svc: unknown module get clock requested: %d\n",
543 msg->module_id);
544 resp.err = AVP_ERR_EINVAL;
545 goto send_response;
546 }
547
548 mutex_lock(&avp_svc->clk_lock);
549 aclk = &avp_svc->clks[mod->clk_req];
550 resp.act_freq = clk_get_rate(aclk->clk);
551 mutex_unlock(&avp_svc->clk_lock);
552 resp.err = 0;
553
554send_response:
555 resp.svc_id = SVC_MODULE_CLOCK_GET_RESPONSE;
556 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
557 sizeof(resp), GFP_KERNEL);
558}
559
560static int dispatch_svc_message(struct avp_svc_info *avp_svc,
561 struct svc_msg *msg,
562 size_t len)
563{
564 int ret = 0;
565
566 switch (msg->svc_id) {
567 case SVC_NVMAP_CREATE:
568 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_create\n", __func__);
569 do_svc_nvmap_create(avp_svc, msg, len);
570 break;
571 case SVC_NVMAP_ALLOC:
572 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_alloc\n", __func__);
573 do_svc_nvmap_alloc(avp_svc, msg, len);
574 break;
575 case SVC_NVMAP_FREE:
576 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_free\n", __func__);
577 do_svc_nvmap_free(avp_svc, msg, len);
578 break;
579 case SVC_NVMAP_PIN:
580 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_pin\n", __func__);
581 do_svc_nvmap_pin(avp_svc, msg, len);
582 break;
583 case SVC_NVMAP_UNPIN:
584 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_unpin\n", __func__);
585 do_svc_nvmap_unpin(avp_svc, msg, len);
586 break;
587 case SVC_NVMAP_FROM_ID:
588 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_from_id\n", __func__);
589 do_svc_nvmap_from_id(avp_svc, msg, len);
590 break;
591 case SVC_NVMAP_GET_ADDRESS:
592 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_get_addr\n", __func__);
593 do_svc_nvmap_get_addr(avp_svc, msg, len);
594 break;
595 case SVC_POWER_REGISTER:
596 DBG(AVP_DBG_TRACE_SVC, "%s: got power_register\n", __func__);
597 do_svc_pwr_register(avp_svc, msg, len);
598 break;
599 case SVC_POWER_UNREGISTER:
600 DBG(AVP_DBG_TRACE_SVC, "%s: got power_unregister\n", __func__);
601 /* nothing to do */
602 break;
603 case SVC_POWER_BUSY_HINT_MULTI:
604 DBG(AVP_DBG_TRACE_SVC, "%s: got power_busy_hint_multi\n",
605 __func__);
606 /* nothing to do */
607 break;
608 case SVC_POWER_BUSY_HINT:
609 case SVC_POWER_STARVATION:
610 DBG(AVP_DBG_TRACE_SVC, "%s: got power busy/starve hint\n",
611 __func__);
612 do_svc_null_response(avp_svc, msg, len, SVC_POWER_RESPONSE);
613 break;
614 case SVC_POWER_MAXFREQ:
615 DBG(AVP_DBG_TRACE_SVC, "%s: got power get_max_freq\n",
616 __func__);
617 do_svc_pwr_max_freq(avp_svc, msg, len);
618 break;
619 case SVC_DFS_GETSTATE:
620 DBG(AVP_DBG_TRACE_SVC, "%s: got dfs_get_state\n", __func__);
621 do_svc_dfs_get_state(avp_svc, msg, len);
622 break;
623 case SVC_MODULE_RESET:
624 DBG(AVP_DBG_TRACE_SVC, "%s: got module_reset\n", __func__);
625 do_svc_module_reset(avp_svc, msg, len);
626 break;
627 case SVC_MODULE_CLOCK:
628 DBG(AVP_DBG_TRACE_SVC, "%s: got module_clock\n", __func__);
629 do_svc_module_clock(avp_svc, msg, len);
630 break;
631 case SVC_DFS_GET_CLK_UTIL:
632 DBG(AVP_DBG_TRACE_SVC, "%s: got get_clk_util\n", __func__);
633 do_svc_dfs_get_clk_util(avp_svc, msg, len);
634 break;
635 case SVC_PRINTF:
636 DBG(AVP_DBG_TRACE_SVC, "%s: got remote printf\n", __func__);
637 do_svc_printf(avp_svc, msg, len);
638 break;
639 case SVC_AVP_WDT_RESET:
640 pr_err("avp_svc: AVP has been reset by watchdog\n");
641 break;
642 case SVC_MODULE_CLOCK_SET:
643 DBG(AVP_DBG_TRACE_SVC, "%s: got module_clock_set\n", __func__);
644 do_svc_module_clock_set(avp_svc, msg, len);
645 break;
646 case SVC_MODULE_CLOCK_GET:
647 DBG(AVP_DBG_TRACE_SVC, "%s: got module_clock_get\n", __func__);
648 do_svc_module_clock_get(avp_svc, msg, len);
649 break;
650 default:
651 pr_warning("avp_svc: Unsupported SVC call 0x%x\n", msg->svc_id);
652 do_svc_unsupported_msg(avp_svc, msg->svc_id);
653 ret = -ENOMSG;
654 break;
655 }
656
657 return ret;
658}
659
660static int avp_svc_thread(void *data)
661{
662 struct avp_svc_info *avp_svc = data;
663 u8 buf[TEGRA_RPC_MAX_MSG_LEN];
664 struct svc_msg *msg = (struct svc_msg *)buf;
665 int ret;
666 long timeout;
667
668 BUG_ON(!avp_svc->cpu_ep);
669
670 ret = trpc_wait_peer(avp_svc->cpu_ep, -1);
671 if (ret) {
672 pr_err("%s: no connection from AVP (%d)\n", __func__, ret);
673 goto err;
674 }
675
676 pr_info("%s: got remote peer\n", __func__);
677
678 while (!kthread_should_stop()) {
679 DBG(AVP_DBG_TRACE_SVC, "%s: waiting for message\n", __func__);
680 ret = trpc_recv_msg(avp_svc->rpc_node, avp_svc->cpu_ep, buf,
681 TEGRA_RPC_MAX_MSG_LEN, -1);
682 DBG(AVP_DBG_TRACE_SVC, "%s: got message\n", __func__);
683
684 if (ret == -ECONNRESET || ret == -ENOTCONN) {
685 wait_queue_head_t wq;
686 init_waitqueue_head(&wq);
687
688 pr_info("%s: AVP seems to be down; "
689 "wait for kthread_stop\n", __func__);
690 timeout = msecs_to_jiffies(100);
691 timeout = wait_event_interruptible_timeout(wq,
692 kthread_should_stop(), timeout);
693 if (timeout == 0)
694 pr_err("%s: timed out while waiting for "
695 "kthread_stop\n", __func__);
696 continue;
697 } else if (ret <= 0) {
698 pr_err("%s: couldn't receive msg (ret=%d)\n",
699 __func__, ret);
700 continue;
701 }
702 dispatch_svc_message(avp_svc, msg, ret);
703 }
704
705err:
706 trpc_put(avp_svc->cpu_ep);
707 pr_info("%s: exiting\n", __func__);
708 return ret;
709}
710
711int avp_svc_start(struct avp_svc_info *avp_svc)
712{
713 struct trpc_endpoint *ep;
714 int ret;
715
716 avp_svc->nvmap_remote = nvmap_create_client(nvmap_dev, "avp_remote");
717 if (IS_ERR(avp_svc->nvmap_remote)) {
718 pr_err("%s: cannot create remote nvmap client\n", __func__);
719 ret = PTR_ERR(avp_svc->nvmap_remote);
720 goto err_nvmap_create_remote_client;
721 }
722
723 ep = trpc_create(avp_svc->rpc_node, "RPC_CPU_PORT", NULL, NULL);
724 if (IS_ERR(ep)) {
725 pr_err("%s: can't create RPC_CPU_PORT\n", __func__);
726 ret = PTR_ERR(ep);
727 goto err_cpu_port_create;
728 }
729
730 /* TODO: protect this */
731 avp_svc->cpu_ep = ep;
732
733 /* the service thread should get an extra reference for the port */
734 trpc_get(avp_svc->cpu_ep);
735 avp_svc->svc_thread = kthread_run(avp_svc_thread, avp_svc,
736 "avp_svc_thread");
737 if (IS_ERR_OR_NULL(avp_svc->svc_thread)) {
738 avp_svc->svc_thread = NULL;
739 pr_err("%s: can't create svc thread\n", __func__);
740 ret = -ENOMEM;
741 goto err_kthread;
742 }
743 return 0;
744
745err_kthread:
746 trpc_close(avp_svc->cpu_ep);
747 trpc_put(avp_svc->cpu_ep);
748 avp_svc->cpu_ep = NULL;
749err_cpu_port_create:
750 nvmap_client_put(avp_svc->nvmap_remote);
751err_nvmap_create_remote_client:
752 avp_svc->nvmap_remote = NULL;
753 return ret;
754}
755
756void avp_svc_stop(struct avp_svc_info *avp_svc)
757{
758 int ret;
759 int i;
760
761 trpc_close(avp_svc->cpu_ep);
762 ret = kthread_stop(avp_svc->svc_thread);
763 if (ret == -EINTR) {
764 /* the thread never started, drop it's extra reference */
765 trpc_put(avp_svc->cpu_ep);
766 }
767 avp_svc->cpu_ep = NULL;
768
769 nvmap_client_put(avp_svc->nvmap_remote);
770 avp_svc->nvmap_remote = NULL;
771
772 mutex_lock(&avp_svc->clk_lock);
773 for (i = 0; i < NUM_CLK_REQUESTS; i++) {
774 struct avp_clk *aclk = &avp_svc->clks[i];
775 BUG_ON(aclk->refcnt < 0);
776 if (aclk->refcnt > 0) {
777 pr_info("%s: remote left clock '%s' on\n", __func__,
778 aclk->mod->name);
779 clk_disable(aclk->clk);
780 /* sclk/emcclk was enabled once for every clock */
781 clk_set_rate(avp_svc->sclk, 0);
782 clk_disable(avp_svc->sclk);
783 clk_set_rate(avp_svc->emcclk, 0);
784 clk_disable(avp_svc->emcclk);
785 }
786 aclk->refcnt = 0;
787 }
788 mutex_unlock(&avp_svc->clk_lock);
789}
790
791struct avp_svc_info *avp_svc_init(struct platform_device *pdev,
792 struct trpc_node *rpc_node)
793{
794 struct tegra_avp_platform_data *pdata;
795 struct avp_svc_info *avp_svc;
796 int ret;
797 int i;
798 int cnt = 0;
799
800 BUG_ON(!rpc_node);
801
802 avp_svc = kzalloc(sizeof(struct avp_svc_info), GFP_KERNEL);
803 if (!avp_svc) {
804 ret = -ENOMEM;
805 goto err_alloc;
806 }
807
808 BUILD_BUG_ON(NUM_CLK_REQUESTS > BITS_PER_LONG);
809
810 pdata = pdev->dev.platform_data;
811
812 for (i = 0; i < NUM_AVP_MODULES; i++) {
813 struct avp_module *mod = &avp_modules[i];
814 struct clk *clk;
815 if (!mod->name)
816 continue;
817 BUG_ON(mod->clk_req >= NUM_CLK_REQUESTS ||
818 cnt++ >= NUM_CLK_REQUESTS);
819
820 clk = clk_get(&pdev->dev, mod->name);
821 if (IS_ERR(clk)) {
822 ret = PTR_ERR(clk);
823 pr_err("avp_svc: Couldn't get required clocks\n");
824 goto err_get_clks;
825 }
826 avp_svc->clks[mod->clk_req].clk = clk;
827 avp_svc->clks[mod->clk_req].mod = mod;
828 avp_svc->clks[mod->clk_req].refcnt = 0;
829 }
830
831 avp_svc->sclk = clk_get(&pdev->dev, "sclk");
832 if (IS_ERR(avp_svc->sclk)) {
833 pr_err("avp_svc: Couldn't get sclk for dvfs\n");
834 ret = -ENOENT;
835 goto err_get_clks;
836 }
837 avp_svc->max_avp_rate = clk_round_rate(avp_svc->sclk, ULONG_MAX);
838 clk_set_rate(avp_svc->sclk, 0);
839
840 avp_svc->emcclk = clk_get(&pdev->dev, "emc");
841 if (IS_ERR(avp_svc->emcclk)) {
842 pr_err("avp_svc: Couldn't get emcclk for dvfs\n");
843 ret = -ENOENT;
844 goto err_get_clks;
845 }
846
847 /*
848 * The emc is a shared clock, it will be set to the rate
849 * requested in platform data. Set the rate to ULONG_MAX
850 * if platform data is NULL.
851 */
852 avp_svc->emc_rate = 0;
853 if (pdata) {
854 clk_set_rate(avp_svc->emcclk, pdata->emc_clk_rate);
855 avp_svc->emc_rate = pdata->emc_clk_rate;
856 }
857 else {
858 clk_set_rate(avp_svc->emcclk, ULONG_MAX);
859 }
860
861 avp_svc->rpc_node = rpc_node;
862
863 mutex_init(&avp_svc->clk_lock);
864
865 return avp_svc;
866
867err_get_clks:
868 for (i = 0; i < NUM_CLK_REQUESTS; i++)
869 if (avp_svc->clks[i].clk)
870 clk_put(avp_svc->clks[i].clk);
871 if (!IS_ERR_OR_NULL(avp_svc->sclk))
872 clk_put(avp_svc->sclk);
873 if (!IS_ERR_OR_NULL(avp_svc->emcclk))
874 clk_put(avp_svc->emcclk);
875 kfree(avp_svc);
876err_alloc:
877 return ERR_PTR(ret);
878}
879
880void avp_svc_destroy(struct avp_svc_info *avp_svc)
881{
882 int i;
883
884 for (i = 0; i < NUM_CLK_REQUESTS; i++)
885 clk_put(avp_svc->clks[i].clk);
886 clk_put(avp_svc->sclk);
887 clk_put(avp_svc->emcclk);
888
889 kfree(avp_svc);
890}
diff --git a/drivers/media/video/tegra/avp/headavp.S b/drivers/media/video/tegra/avp/headavp.S
new file mode 100644
index 00000000000..c1f8e9fea1c
--- /dev/null
+++ b/drivers/media/video/tegra/avp/headavp.S
@@ -0,0 +1,68 @@
1/*
2 * arch/arm/mach-tegra/headavp.S
3 *
4 * AVP kernel launcher stub; programs the AVP MMU and jumps to the
5 * kernel code. Must use ONLY ARMv4 instructions, and must be compiled
6 * in ARM mode.
7 *
8 * Copyright (c) 2010, NVIDIA Corporation.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24
25#include <linux/linkage.h>
26#include <asm/assembler.h>
27#include "headavp.h"
28
29#define PTE0_COMPARE 0
30/* the default translation will translate any VA within
31 * 0x0010:0000..0x001f:ffff to the (megabyte-aligned) value written to
32 * _tegra_avp_boot_stub_data.map_phys_addr
33 */
34#define PTE0_DEFAULT (AVP_KERNEL_VIRT_BASE | 0x3ff0)
35
36#define PTE0_TRANSLATE 4
37
38#define TRANSLATE_DATA (1 << 11)
39#define TRANSLATE_CODE (1 << 10)
40#define TRANSLATE_WR (1 << 9)
41#define TRANSLATE_RD (1 << 8)
42#define TRANSLATE_HIT (1 << 7)
43#define TRANSLATE_EN (1 << 2)
44
45#define TRANSLATE_OPT (TRANSLATE_DATA | TRANSLATE_CODE | TRANSLATE_WR | \
46 TRANSLATE_RD | TRANSLATE_HIT)
47
48ENTRY(_tegra_avp_boot_stub)
49 adr r4, _tegra_avp_boot_stub_data
50 ldmia r4, {r0-r3}
51#ifdef CONFIG_TEGRA_AVP_KERNEL_ON_MMU
52 str r2, [r0, #PTE0_COMPARE]
53 bic r3, r3, #0xff0
54 bic r3, r3, #0x00f
55 orr r3, r3, #TRANSLATE_OPT
56 orr r3, r3, #TRANSLATE_EN
57 str r3, [r0, #PTE0_TRANSLATE]
58#endif
59 bx r1
60 b .
61ENDPROC(_tegra_avp_boot_stub)
62 .type _tegra_avp_boot_stub_data, %object
63ENTRY(_tegra_avp_boot_stub_data)
64 .long AVP_MMU_TLB_BASE
65 .long 0xdeadbeef
66 .long PTE0_DEFAULT
67 .long 0xdeadd00d
68 .size _tegra_avp_boot_stub_data, . - _tegra_avp_boot_stub_data
diff --git a/drivers/media/video/tegra/avp/headavp.h b/drivers/media/video/tegra/avp/headavp.h
new file mode 100644
index 00000000000..2bcc3297bfa
--- /dev/null
+++ b/drivers/media/video/tegra/avp/headavp.h
@@ -0,0 +1,41 @@
1/*
2 * arch/arm/mach-tegra/headavp.h
3 *
4 * Copyright (c) 2010, NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#ifndef _MACH_TEGRA_HEADAVP_H
22#define _MACH_TEGRA_HEADAVP_H
23
24#define AVP_MMU_TLB_BASE 0xF000F000
25#define AVP_KERNEL_VIRT_BASE 0x00100000
26
27#ifndef __ASSEMBLY__
28
29struct tegra_avp_boot_stub_data {
30 unsigned long mmu_tlb_base;
31 unsigned long jump_addr;
32 unsigned long map_virt_addr;
33 unsigned long map_phys_addr;
34};
35
36extern void _tegra_avp_boot_stub(void);
37extern struct tegra_avp_boot_stub_data _tegra_avp_boot_stub_data;
38
39#endif
40
41#endif
diff --git a/drivers/media/video/tegra/avp/nvavp.h b/drivers/media/video/tegra/avp/nvavp.h
new file mode 100644
index 00000000000..dbc62b48588
--- /dev/null
+++ b/drivers/media/video/tegra/avp/nvavp.h
@@ -0,0 +1,53 @@
1/*
2 * Copyright (C) 2011 Nvidia Corp
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#ifndef __MEDIA_VIDEO_TEGRA_NVAVP_H
16#define __MEDIA_VIDEO_TEGRA_NVAVP_H
17
18#include <linux/tegra_avp.h>
19
20struct tegra_avp_info;
21
22int tegra_avp_open(struct tegra_avp_info **avp);
23int tegra_avp_release(struct tegra_avp_info *avp);
24int tegra_avp_load_lib(struct tegra_avp_info *avp, struct tegra_avp_lib *lib);
25int tegra_avp_unload_lib(struct tegra_avp_info *avp, unsigned long handle);
26
27
28#include <linux/tegra_sema.h>
29
30struct tegra_sema_info;
31
32int tegra_sema_open(struct tegra_sema_info **sema);
33int tegra_sema_release(struct tegra_sema_info *sema);
34int tegra_sema_wait(struct tegra_sema_info *sema, long* timeout);
35int tegra_sema_signal(struct tegra_sema_info *sema);
36
37
38#include <linux/tegra_rpc.h>
39
40struct tegra_rpc_info;
41
42int tegra_rpc_open(struct tegra_rpc_info **rpc);
43int tegra_rpc_release(struct tegra_rpc_info *rpc);
44int tegra_rpc_port_create(struct tegra_rpc_info *rpc, char *name,
45 struct tegra_sema_info *sema);
46int tegra_rpc_get_name(struct tegra_rpc_info *rpc, char* name);
47int tegra_rpc_port_connect(struct tegra_rpc_info *rpc, long timeout);
48int tegra_rpc_port_listen(struct tegra_rpc_info *rpc, long timeout);
49int tegra_rpc_write(struct tegra_rpc_info *rpc, u8* buf, size_t size);
50int tegra_rpc_read(struct tegra_rpc_info *rpc, u8 *buf, size_t max);
51
52
53#endif
diff --git a/drivers/media/video/tegra/avp/tegra_rpc.c b/drivers/media/video/tegra/avp/tegra_rpc.c
new file mode 100644
index 00000000000..a0fd1dc999f
--- /dev/null
+++ b/drivers/media/video/tegra/avp/tegra_rpc.c
@@ -0,0 +1,796 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 *
4 * Author:
5 * Dima Zavin <dima@android.com>
6 *
7 * Based on original NVRM code from NVIDIA, and a partial rewrite by:
8 * Gary King <gking@nvidia.com>
9 *
10 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and
12 * may be copied, distributed, and modified under those terms.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 */
20
21#include <linux/debugfs.h>
22#include <linux/delay.h>
23#include <linux/err.h>
24#include <linux/kref.h>
25#include <linux/list.h>
26#include <linux/module.h>
27#include <linux/mutex.h>
28#include <linux/rbtree.h>
29#include <linux/sched.h>
30#include <linux/seq_file.h>
31#include <linux/slab.h>
32#include <linux/tegra_rpc.h>
33#include <linux/types.h>
34#include <linux/wait.h>
35
36#include "trpc.h"
37
38struct trpc_port;
39struct trpc_endpoint {
40 struct list_head msg_list;
41 wait_queue_head_t msg_waitq;
42
43 struct trpc_endpoint *out;
44 struct trpc_port *port;
45
46 struct trpc_node *owner;
47
48 struct completion *connect_done;
49 bool ready;
50 struct trpc_ep_ops *ops;
51 void *priv;
52};
53
54struct trpc_port {
55 char name[TEGRA_RPC_MAX_NAME_LEN];
56
57 /* protects peer and closed state */
58 spinlock_t lock;
59 struct trpc_endpoint peers[2];
60 bool closed;
61
62 /* private */
63 struct kref ref;
64 struct rb_node rb_node;
65};
66
67enum {
68 TRPC_TRACE_MSG = 1U << 0,
69 TRPC_TRACE_CONN = 1U << 1,
70 TRPC_TRACE_PORT = 1U << 2,
71};
72
73static u32 trpc_debug_mask;
74module_param_named(debug_mask, trpc_debug_mask, uint, S_IWUSR | S_IRUGO);
75
76#define DBG(flag, args...) \
77 do { if (trpc_debug_mask & (flag)) pr_info(args); } while (0)
78
79struct tegra_rpc_info {
80 struct kmem_cache *msg_cache;
81
82 spinlock_t ports_lock;
83 struct rb_root ports;
84
85 struct list_head node_list;
86 struct mutex node_lock;
87};
88
89struct trpc_msg {
90 struct list_head list;
91
92 size_t len;
93 u8 payload[TEGRA_RPC_MAX_MSG_LEN];
94};
95
96static struct tegra_rpc_info *tegra_rpc;
97static struct dentry *trpc_debug_root;
98
99static struct trpc_msg *dequeue_msg_locked(struct trpc_endpoint *ep);
100
101/* a few accessors for the outside world to keep the trpc_endpoint struct
102 * definition private to this module */
103void *trpc_priv(struct trpc_endpoint *ep)
104{
105 return ep->priv;
106}
107
108struct trpc_endpoint *trpc_peer(struct trpc_endpoint *ep)
109{
110 return ep->out;
111}
112
113const char *trpc_name(struct trpc_endpoint *ep)
114{
115 return ep->port->name;
116}
117
118static inline bool is_connected(struct trpc_port *port)
119{
120 return port->peers[0].ready && port->peers[1].ready;
121}
122
123static inline bool is_closed(struct trpc_port *port)
124{
125 return port->closed;
126}
127
128static void rpc_port_free(struct tegra_rpc_info *info, struct trpc_port *port)
129{
130 struct trpc_msg *msg;
131 int i;
132
133 for (i = 0; i < 2; ++i) {
134 struct list_head *list = &port->peers[i].msg_list;
135 while (!list_empty(list)) {
136 msg = list_first_entry(list, struct trpc_msg, list);
137 list_del(&msg->list);
138 kmem_cache_free(info->msg_cache, msg);
139 }
140 }
141 kfree(port);
142}
143
144static void _rpc_port_release(struct kref *kref)
145{
146 struct tegra_rpc_info *info = tegra_rpc;
147 struct trpc_port *port = container_of(kref, struct trpc_port, ref);
148 unsigned long flags;
149
150 DBG(TRPC_TRACE_PORT, "%s: releasing port '%s' (%p)\n", __func__,
151 port->name, port);
152 spin_lock_irqsave(&info->ports_lock, flags);
153 rb_erase(&port->rb_node, &info->ports);
154 spin_unlock_irqrestore(&info->ports_lock, flags);
155 rpc_port_free(info, port);
156}
157
158/* note that the refcount is actually on the port and not on the endpoint */
159void trpc_put(struct trpc_endpoint *ep)
160{
161 kref_put(&ep->port->ref, _rpc_port_release);
162}
163
164void trpc_get(struct trpc_endpoint *ep)
165{
166 kref_get(&ep->port->ref);
167}
168
169/* Searches the rb_tree for a port with the provided name. If one is not found,
170 * the new port in inserted. Otherwise, the existing port is returned.
171 * Must be called with the ports_lock held */
172static struct trpc_port *rpc_port_find_insert(struct tegra_rpc_info *info,
173 struct trpc_port *port)
174{
175 struct rb_node **p;
176 struct rb_node *parent;
177 struct trpc_port *tmp;
178 int ret = 0;
179
180 p = &info->ports.rb_node;
181 parent = NULL;
182 while (*p) {
183 parent = *p;
184 tmp = rb_entry(parent, struct trpc_port, rb_node);
185
186 ret = strncmp(port->name, tmp->name, TEGRA_RPC_MAX_NAME_LEN);
187 if (ret < 0)
188 p = &(*p)->rb_left;
189 else if (ret > 0)
190 p = &(*p)->rb_right;
191 else
192 return tmp;
193 }
194 rb_link_node(&port->rb_node, parent, p);
195 rb_insert_color(&port->rb_node, &info->ports);
196 DBG(TRPC_TRACE_PORT, "%s: inserted port '%s' (%p)\n", __func__,
197 port->name, port);
198 return port;
199}
200
201static int nodes_try_connect(struct tegra_rpc_info *info,
202 struct trpc_node *src,
203 struct trpc_endpoint *from)
204{
205 struct trpc_node *node;
206 int ret;
207
208 mutex_lock(&info->node_lock);
209 list_for_each_entry(node, &info->node_list, list) {
210 if (!node->try_connect)
211 continue;
212 ret = node->try_connect(node, src, from);
213 if (!ret) {
214 mutex_unlock(&info->node_lock);
215 return 0;
216 }
217 }
218 mutex_unlock(&info->node_lock);
219 return -ECONNREFUSED;
220}
221
222static struct trpc_port *rpc_port_alloc(const char *name)
223{
224 struct trpc_port *port;
225 int i;
226
227 port = kzalloc(sizeof(struct trpc_port), GFP_KERNEL);
228 if (!port) {
229 pr_err("%s: can't alloc rpc_port\n", __func__);
230 return NULL;
231 }
232 BUILD_BUG_ON(2 != ARRAY_SIZE(port->peers));
233
234 spin_lock_init(&port->lock);
235 kref_init(&port->ref);
236 strlcpy(port->name, name, TEGRA_RPC_MAX_NAME_LEN);
237 for (i = 0; i < 2; i++) {
238 struct trpc_endpoint *ep = port->peers + i;
239 INIT_LIST_HEAD(&ep->msg_list);
240 init_waitqueue_head(&ep->msg_waitq);
241 ep->port = port;
242 }
243 port->peers[0].out = &port->peers[1];
244 port->peers[1].out = &port->peers[0];
245
246 return port;
247}
248
249/* must be holding the ports lock */
250static inline void handle_port_connected(struct trpc_port *port)
251{
252 int i;
253
254 DBG(TRPC_TRACE_CONN, "tegra_rpc: port '%s' connected\n", port->name);
255
256 for (i = 0; i < 2; i++)
257 if (port->peers[i].connect_done)
258 complete(port->peers[i].connect_done);
259}
260
261static inline void _ready_ep(struct trpc_endpoint *ep,
262 struct trpc_node *owner,
263 struct trpc_ep_ops *ops,
264 void *priv)
265{
266 ep->ready = true;
267 ep->owner = owner;
268 ep->ops = ops;
269 ep->priv = priv;
270}
271
272/* this keeps a reference on the port */
273static struct trpc_endpoint *_create_peer(struct tegra_rpc_info *info,
274 struct trpc_node *owner,
275 struct trpc_endpoint *ep,
276 struct trpc_ep_ops *ops,
277 void *priv)
278{
279 struct trpc_port *port = ep->port;
280 struct trpc_endpoint *peer = ep->out;
281 unsigned long flags;
282
283 spin_lock_irqsave(&port->lock, flags);
284 BUG_ON(port->closed);
285 if (peer->ready || !ep->ready) {
286 peer = NULL;
287 goto out;
288 }
289 _ready_ep(peer, owner, ops, priv);
290 if (WARN_ON(!is_connected(port)))
291 pr_warning("%s: created peer but no connection established?!\n",
292 __func__);
293 else
294 handle_port_connected(port);
295 trpc_get(peer);
296out:
297 spin_unlock_irqrestore(&port->lock, flags);
298 return peer;
299}
300
301/* Exported code. This is out interface to the outside world */
302struct trpc_endpoint *trpc_create(struct trpc_node *owner, const char *name,
303 struct trpc_ep_ops *ops, void *priv)
304{
305 struct tegra_rpc_info *info = tegra_rpc;
306 struct trpc_endpoint *ep;
307 struct trpc_port *new_port;
308 struct trpc_port *port;
309 unsigned long flags;
310
311 BUG_ON(!owner);
312
313 /* we always allocate a new port even if one already might exist. This
314 * is slightly inefficient, but it allows us to do the allocation
315 * without holding our ports_lock spinlock. */
316 new_port = rpc_port_alloc(name);
317 if (!new_port) {
318 pr_err("%s: can't allocate memory for '%s'\n", __func__, name);
319 return ERR_PTR(-ENOMEM);
320 }
321
322 spin_lock_irqsave(&info->ports_lock, flags);
323 port = rpc_port_find_insert(info, new_port);
324 if (port != new_port) {
325 rpc_port_free(info, new_port);
326 /* There was already a port by that name in the rb_tree,
327 * so just try to create its peer[1], i.e. peer for peer[0]
328 */
329 ep = _create_peer(info, owner, &port->peers[0], ops, priv);
330 if (!ep) {
331 pr_err("%s: port '%s' is not in a connectable state\n",
332 __func__, port->name);
333 ep = ERR_PTR(-EINVAL);
334 }
335 goto out;
336 }
337 /* don't need to grab the individual port lock here since we must be
338 * holding the ports_lock to add the new element, and never dropped
339 * it, and thus noone could have gotten a reference to this port
340 * and thus the state couldn't have been touched */
341 ep = &port->peers[0];
342 _ready_ep(ep, owner, ops, priv);
343out:
344 spin_unlock_irqrestore(&info->ports_lock, flags);
345 return ep;
346}
347
348struct trpc_endpoint *trpc_create_peer(struct trpc_node *owner,
349 struct trpc_endpoint *ep,
350 struct trpc_ep_ops *ops,
351 void *priv)
352{
353 struct tegra_rpc_info *info = tegra_rpc;
354 struct trpc_endpoint *peer;
355 unsigned long flags;
356
357 BUG_ON(!owner);
358
359 spin_lock_irqsave(&info->ports_lock, flags);
360 peer = _create_peer(info, owner, ep, ops, priv);
361 spin_unlock_irqrestore(&info->ports_lock, flags);
362 return peer;
363}
364
365/* timeout == -1, waits forever
366 * timeout == 0, return immediately
367 */
368int trpc_connect(struct trpc_endpoint *from, long timeout)
369{
370 struct tegra_rpc_info *info = tegra_rpc;
371 struct trpc_port *port = from->port;
372 struct trpc_node *src = from->owner;
373 int ret;
374 bool no_retry = !timeout;
375 unsigned long endtime = jiffies + msecs_to_jiffies(timeout);
376 unsigned long flags;
377
378 spin_lock_irqsave(&port->lock, flags);
379 /* XXX: add state for connections and ports to prevent invalid
380 * states like multiple connections, etc. ? */
381 if (unlikely(is_closed(port))) {
382 ret = -ECONNRESET;
383 pr_err("%s: can't connect to %s, closed\n", __func__,
384 port->name);
385 goto out;
386 } else if (is_connected(port)) {
387 ret = 0;
388 goto out;
389 }
390 spin_unlock_irqrestore(&port->lock, flags);
391
392 do {
393 ret = nodes_try_connect(info, src, from);
394
395 spin_lock_irqsave(&port->lock, flags);
396 if (is_connected(port)) {
397 ret = 0;
398 goto out;
399 } else if (no_retry) {
400 goto out;
401 } else if (signal_pending(current)) {
402 ret = -EINTR;
403 goto out;
404 }
405 spin_unlock_irqrestore(&port->lock, flags);
406 usleep_range(5000, 20000);
407 } while (timeout < 0 || time_before(jiffies, endtime));
408
409 return -ETIMEDOUT;
410
411out:
412 spin_unlock_irqrestore(&port->lock, flags);
413 return ret;
414}
415
416/* convenience function for doing this common pattern in a single call */
417struct trpc_endpoint *trpc_create_connect(struct trpc_node *src,
418 char *name,
419 struct trpc_ep_ops *ops,
420 void *priv,
421 long timeout)
422{
423 struct trpc_endpoint *ep;
424 int ret;
425
426 ep = trpc_create(src, name, ops, priv);
427 if (IS_ERR(ep))
428 return ep;
429
430 ret = trpc_connect(ep, timeout);
431 if (ret) {
432 trpc_close(ep);
433 return ERR_PTR(ret);
434 }
435
436 return ep;
437}
438
439void trpc_close(struct trpc_endpoint *ep)
440{
441 struct trpc_port *port = ep->port;
442 struct trpc_endpoint *peer = ep->out;
443 bool need_close_op = false;
444 unsigned long flags;
445
446 spin_lock_irqsave(&port->lock, flags);
447 BUG_ON(!ep->ready);
448 ep->ready = false;
449 port->closed = true;
450 if (peer->ready) {
451 need_close_op = true;
452 /* the peer may be waiting for a message */
453 wake_up_all(&peer->msg_waitq);
454 if (peer->connect_done)
455 complete(peer->connect_done);
456 }
457 spin_unlock_irqrestore(&port->lock, flags);
458 if (need_close_op && peer->ops && peer->ops->close)
459 peer->ops->close(peer);
460 trpc_put(ep);
461}
462
463int trpc_wait_peer(struct trpc_endpoint *ep, long timeout)
464{
465 struct trpc_port *port = ep->port;
466 DECLARE_COMPLETION_ONSTACK(event);
467 int ret;
468 unsigned long flags;
469
470 if (timeout < 0)
471 timeout = MAX_SCHEDULE_TIMEOUT;
472 else if (timeout > 0)
473 timeout = msecs_to_jiffies(timeout);
474
475 spin_lock_irqsave(&port->lock, flags);
476 if (ep->connect_done) {
477 ret = -EBUSY;
478 goto done;
479 } else if (is_connected(port)) {
480 ret = 0;
481 goto done;
482 } else if (is_closed(port)) {
483 ret = -ECONNRESET;
484 goto done;
485 } else if (!timeout) {
486 ret = -EAGAIN;
487 goto done;
488 }
489 ep->connect_done = &event;
490 spin_unlock_irqrestore(&port->lock, flags);
491
492 ret = wait_for_completion_interruptible_timeout(&event, timeout);
493
494 spin_lock_irqsave(&port->lock, flags);
495 ep->connect_done = NULL;
496
497 if (is_connected(port)) {
498 ret = 0;
499 } else {
500 if (is_closed(port))
501 ret = -ECONNRESET;
502 else if (ret == -ERESTARTSYS)
503 ret = -EINTR;
504 else if (!ret)
505 ret = -ETIMEDOUT;
506 }
507
508done:
509 spin_unlock_irqrestore(&port->lock, flags);
510 return ret;
511}
512
513static inline int _ep_id(struct trpc_endpoint *ep)
514{
515 return ep - ep->port->peers;
516}
517
518static int queue_msg(struct trpc_node *src, struct trpc_endpoint *from,
519 void *buf, size_t len, gfp_t gfp_flags)
520{
521 struct tegra_rpc_info *info = tegra_rpc;
522 struct trpc_endpoint *peer = from->out;
523 struct trpc_port *port = from->port;
524 struct trpc_msg *msg;
525 unsigned long flags;
526 int ret;
527
528 BUG_ON(len > TEGRA_RPC_MAX_MSG_LEN);
529 /* shouldn't be enqueueing to the endpoint */
530 BUG_ON(peer->ops && peer->ops->send);
531
532 DBG(TRPC_TRACE_MSG, "%s: queueing message for %s.%d\n", __func__,
533 port->name, _ep_id(peer));
534
535 msg = kmem_cache_alloc(info->msg_cache, gfp_flags);
536 if (!msg) {
537 pr_err("%s: can't alloc memory for msg\n", __func__);
538 return -ENOMEM;
539 }
540
541 memcpy(msg->payload, buf, len);
542 msg->len = len;
543
544 spin_lock_irqsave(&port->lock, flags);
545 if (is_closed(port)) {
546 pr_err("%s: cannot send message for closed port %s.%d\n",
547 __func__, port->name, _ep_id(peer));
548 ret = -ECONNRESET;
549 goto err;
550 } else if (!is_connected(port)) {
551 pr_err("%s: cannot send message for unconnected port %s.%d\n",
552 __func__, port->name, _ep_id(peer));
553 ret = -ENOTCONN;
554 goto err;
555 }
556
557 list_add_tail(&msg->list, &peer->msg_list);
558 if (peer->ops && peer->ops->notify_recv)
559 peer->ops->notify_recv(peer);
560 wake_up_all(&peer->msg_waitq);
561 spin_unlock_irqrestore(&port->lock, flags);
562 return 0;
563
564err:
565 spin_unlock_irqrestore(&port->lock, flags);
566 kmem_cache_free(info->msg_cache, msg);
567 return ret;
568}
569
570/* Returns -ENOMEM if failed to allocate memory for the message. */
571int trpc_send_msg(struct trpc_node *src, struct trpc_endpoint *from,
572 void *buf, size_t len, gfp_t gfp_flags)
573{
574 struct trpc_endpoint *peer = from->out;
575 struct trpc_port *port = from->port;
576
577 BUG_ON(len > TEGRA_RPC_MAX_MSG_LEN);
578
579 DBG(TRPC_TRACE_MSG, "%s: sending message from %s.%d to %s.%d\n",
580 __func__, port->name, _ep_id(from), port->name, _ep_id(peer));
581
582 if (peer->ops && peer->ops->send) {
583 might_sleep();
584 return peer->ops->send(peer, buf, len);
585 } else {
586 might_sleep_if(gfp_flags & __GFP_WAIT);
587 return queue_msg(src, from, buf, len, gfp_flags);
588 }
589}
590
591static inline struct trpc_msg *dequeue_msg_locked(struct trpc_endpoint *ep)
592{
593 struct trpc_msg *msg = NULL;
594
595 if (!list_empty(&ep->msg_list)) {
596 msg = list_first_entry(&ep->msg_list, struct trpc_msg, list);
597 list_del_init(&msg->list);
598 }
599
600 return msg;
601}
602
603static bool __should_wake(struct trpc_endpoint *ep)
604{
605 struct trpc_port *port = ep->port;
606 unsigned long flags;
607 bool ret;
608
609 spin_lock_irqsave(&port->lock, flags);
610 ret = !list_empty(&ep->msg_list) || is_closed(port);
611 spin_unlock_irqrestore(&port->lock, flags);
612 return ret;
613}
614
615int trpc_recv_msg(struct trpc_node *src, struct trpc_endpoint *ep,
616 void *buf, size_t buf_len, long timeout)
617{
618 struct tegra_rpc_info *info = tegra_rpc;
619 struct trpc_port *port = ep->port;
620 struct trpc_msg *msg;
621 size_t len;
622 long ret;
623 unsigned long flags;
624
625 BUG_ON(buf_len > TEGRA_RPC_MAX_MSG_LEN);
626
627 spin_lock_irqsave(&port->lock, flags);
628 /* we allow closed ports to finish receiving already-queued messages */
629 msg = dequeue_msg_locked(ep);
630 if (msg) {
631 goto got_msg;
632 } else if (is_closed(port)) {
633 ret = -ECONNRESET;
634 goto out;
635 } else if (!is_connected(port)) {
636 ret = -ENOTCONN;
637 goto out;
638 }
639
640 if (timeout == 0) {
641 ret = 0;
642 goto out;
643 } else if (timeout < 0) {
644 timeout = MAX_SCHEDULE_TIMEOUT;
645 } else {
646 timeout = msecs_to_jiffies(timeout);
647 }
648 spin_unlock_irqrestore(&port->lock, flags);
649 DBG(TRPC_TRACE_MSG, "%s: waiting for message for %s.%d\n", __func__,
650 port->name, _ep_id(ep));
651
652 ret = wait_event_interruptible_timeout(ep->msg_waitq, __should_wake(ep),
653 timeout);
654
655 DBG(TRPC_TRACE_MSG, "%s: woke up for %s\n", __func__, port->name);
656 spin_lock_irqsave(&port->lock, flags);
657 msg = dequeue_msg_locked(ep);
658 if (!msg) {
659 if (is_closed(port))
660 ret = -ECONNRESET;
661 else if (!ret)
662 ret = -ETIMEDOUT;
663 else if (ret == -ERESTARTSYS)
664 ret = -EINTR;
665 else
666 pr_err("%s: error (%d) while receiving msg for '%s'\n",
667 __func__, (int)ret, port->name);
668 goto out;
669 }
670
671got_msg:
672 spin_unlock_irqrestore(&port->lock, flags);
673 len = min(buf_len, msg->len);
674 memcpy(buf, msg->payload, len);
675 kmem_cache_free(info->msg_cache, msg);
676 return len;
677
678out:
679 spin_unlock_irqrestore(&port->lock, flags);
680 return ret;
681}
682
683int trpc_node_register(struct trpc_node *node)
684{
685 struct tegra_rpc_info *info = tegra_rpc;
686
687 if (!info)
688 return -ENOMEM;
689
690 pr_info("%s: Adding '%s' to node list\n", __func__, node->name);
691
692 mutex_lock(&info->node_lock);
693 if (node->type == TRPC_NODE_LOCAL)
694 list_add(&node->list, &info->node_list);
695 else
696 list_add_tail(&node->list, &info->node_list);
697 mutex_unlock(&info->node_lock);
698 return 0;
699}
700
701void trpc_node_unregister(struct trpc_node *node)
702{
703 struct tegra_rpc_info *info = tegra_rpc;
704
705 mutex_lock(&info->node_lock);
706 list_del(&node->list);
707 mutex_unlock(&info->node_lock);
708}
709
710static int trpc_debug_ports_show(struct seq_file *s, void *data)
711{
712 struct tegra_rpc_info *info = s->private;
713 struct rb_node *n;
714 unsigned long flags;
715 int i;
716
717 spin_lock_irqsave(&info->ports_lock, flags);
718 for (n = rb_first(&info->ports); n; n = rb_next(n)) {
719 struct trpc_port *port = rb_entry(n, struct trpc_port, rb_node);
720 seq_printf(s, "port: %s\n closed:%s\n", port->name,
721 port->closed ? "yes" : "no");
722
723 spin_lock(&port->lock);
724 for (i = 0; i < ARRAY_SIZE(port->peers); i++) {
725 struct trpc_endpoint *ep = &port->peers[i];
726 seq_printf(s, " peer%d: %s\n ready:%s\n", i,
727 ep->owner ? ep->owner->name : "<none>",
728 ep->ready ? "yes" : "no");
729 if (ep->ops && ep->ops->show)
730 ep->ops->show(s, ep);
731 }
732 spin_unlock(&port->lock);
733 }
734 spin_unlock_irqrestore(&info->ports_lock, flags);
735
736 return 0;
737}
738
739static int trpc_debug_ports_open(struct inode *inode, struct file *file)
740{
741 return single_open(file, trpc_debug_ports_show, inode->i_private);
742}
743
744static const struct file_operations trpc_debug_ports_fops = {
745 .open = trpc_debug_ports_open,
746 .read = seq_read,
747 .llseek = seq_lseek,
748 .release = single_release,
749};
750
751static void trpc_debug_init(struct tegra_rpc_info *info)
752{
753 trpc_debug_root = debugfs_create_dir("tegra_rpc", NULL);
754 if (IS_ERR_OR_NULL(trpc_debug_root)) {
755 pr_err("%s: couldn't create debug files\n", __func__);
756 return;
757 }
758
759 debugfs_create_file("ports", 0664, trpc_debug_root, info,
760 &trpc_debug_ports_fops);
761}
762
763static int __init tegra_rpc_init(void)
764{
765 struct tegra_rpc_info *rpc_info;
766 int ret;
767
768 rpc_info = kzalloc(sizeof(struct tegra_rpc_info), GFP_KERNEL);
769 if (!rpc_info) {
770 pr_err("%s: error allocating rpc_info\n", __func__);
771 return -ENOMEM;
772 }
773
774 rpc_info->ports = RB_ROOT;
775 spin_lock_init(&rpc_info->ports_lock);
776 INIT_LIST_HEAD(&rpc_info->node_list);
777 mutex_init(&rpc_info->node_lock);
778
779 rpc_info->msg_cache = KMEM_CACHE(trpc_msg, 0);
780 if (!rpc_info->msg_cache) {
781 pr_err("%s: unable to create message cache\n", __func__);
782 ret = -ENOMEM;
783 goto err_kmem_cache;
784 }
785
786 trpc_debug_init(rpc_info);
787 tegra_rpc = rpc_info;
788
789 return 0;
790
791err_kmem_cache:
792 kfree(rpc_info);
793 return ret;
794}
795
796subsys_initcall(tegra_rpc_init);
diff --git a/drivers/media/video/tegra/avp/trpc.h b/drivers/media/video/tegra/avp/trpc.h
new file mode 100644
index 00000000000..e7b0d2d5578
--- /dev/null
+++ b/drivers/media/video/tegra/avp/trpc.h
@@ -0,0 +1,80 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 *
4 * Author:
5 * Dima Zavin <dima@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#ifndef __ARM_MACH_TEGRA_RPC_H
19#define __ARM_MACH_TEGRA_RPC_H
20
21#include <linux/list.h>
22#include <linux/seq_file.h>
23#include <linux/tegra_rpc.h>
24
25struct trpc_endpoint;
26struct trpc_ep_ops {
27 /* send is allowed to sleep */
28 int (*send)(struct trpc_endpoint *ep, void *buf, size_t len);
29 /* notify_recv is NOT allowed to sleep */
30 void (*notify_recv)(struct trpc_endpoint *ep);
31 /* close is allowed to sleep */
32 void (*close)(struct trpc_endpoint *ep);
33 /* not allowed to sleep, not allowed to call back into trpc */
34 void (*show)(struct seq_file *s, struct trpc_endpoint *ep);
35};
36
37enum {
38 TRPC_NODE_LOCAL,
39 TRPC_NODE_REMOTE,
40};
41
42struct trpc_node {
43 struct list_head list;
44 const char *name;
45 int type;
46 void *priv;
47
48 int (*try_connect)(struct trpc_node *node,
49 struct trpc_node *src,
50 struct trpc_endpoint *from);
51};
52
53struct trpc_endpoint *trpc_peer(struct trpc_endpoint *ep);
54void *trpc_priv(struct trpc_endpoint *ep);
55const char *trpc_name(struct trpc_endpoint *ep);
56
57void trpc_put(struct trpc_endpoint *ep);
58void trpc_get(struct trpc_endpoint *ep);
59
60int trpc_send_msg(struct trpc_node *src, struct trpc_endpoint *ep, void *buf,
61 size_t len, gfp_t gfp_flags);
62int trpc_recv_msg(struct trpc_node *src, struct trpc_endpoint *ep,
63 void *buf, size_t len, long timeout);
64struct trpc_endpoint *trpc_create(struct trpc_node *owner, const char *name,
65 struct trpc_ep_ops *ops, void *priv);
66struct trpc_endpoint *trpc_create_connect(struct trpc_node *src, char *name,
67 struct trpc_ep_ops *ops, void *priv,
68 long timeout);
69int trpc_connect(struct trpc_endpoint *from, long timeout);
70struct trpc_endpoint *trpc_create_peer(struct trpc_node *owner,
71 struct trpc_endpoint *ep,
72 struct trpc_ep_ops *ops,
73 void *priv);
74void trpc_close(struct trpc_endpoint *ep);
75int trpc_wait_peer(struct trpc_endpoint *ep, long timeout);
76
77int trpc_node_register(struct trpc_node *node);
78void trpc_node_unregister(struct trpc_node *node);
79
80#endif
diff --git a/drivers/media/video/tegra/avp/trpc_local.c b/drivers/media/video/tegra/avp/trpc_local.c
new file mode 100644
index 00000000000..77692e09438
--- /dev/null
+++ b/drivers/media/video/tegra/avp/trpc_local.c
@@ -0,0 +1,419 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 *
4 * Author:
5 * Dima Zavin <dima@android.com>
6 *
7 * Based on original NVRM code from NVIDIA, and a partial rewrite by
8 * Gary King <gking@nvidia.com>
9 *
10 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and
12 * may be copied, distributed, and modified under those terms.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 */
20
21#include <linux/err.h>
22#include <linux/file.h>
23#include <linux/fs.h>
24#include <linux/list.h>
25#include <linux/miscdevice.h>
26#include <linux/sched.h>
27#include <linux/slab.h>
28#include <linux/spinlock.h>
29#include <linux/tegra_rpc.h>
30#include <linux/types.h>
31#include <linux/uaccess.h>
32#include <linux/wait.h>
33
34#include "trpc.h"
35#include "trpc_sema.h"
36#include "nvavp.h"
37
38struct tegra_rpc_info {
39 struct trpc_endpoint *rpc_ep;
40 struct tegra_sema_info *sema;
41};
42
43/* ports names reserved for system functions, i.e. communicating with the
44 * AVP */
45static const char reserved_ports[][TEGRA_RPC_MAX_NAME_LEN] = {
46 "RPC_AVP_PORT",
47 "RPC_CPU_PORT",
48};
49static int num_reserved_ports = ARRAY_SIZE(reserved_ports);
50
51static void rpc_notify_recv(struct trpc_endpoint *ep);
52
53/* TODO: do we need to do anything when port is closed from the other side? */
54static struct trpc_ep_ops ep_ops = {
55 .notify_recv = rpc_notify_recv,
56};
57
58static struct trpc_node rpc_node = {
59 .name = "local",
60 .type = TRPC_NODE_LOCAL,
61};
62
63static void rpc_notify_recv(struct trpc_endpoint *ep)
64{
65 struct tegra_rpc_info *info = trpc_priv(ep);
66
67 if (WARN_ON(!info))
68 return;
69 if (info->sema)
70 tegra_sema_signal(info->sema);
71}
72
73int tegra_rpc_open(struct tegra_rpc_info **info)
74{
75 struct tegra_rpc_info *new_info;
76
77 new_info = kzalloc(sizeof(struct tegra_rpc_info), GFP_KERNEL);
78 if (!new_info)
79 return -ENOMEM;
80
81 *info = new_info;
82 return 0;
83}
84
85static int local_rpc_open(struct inode *inode, struct file *file)
86{
87 struct tegra_rpc_info *info;
88 int ret = 0;
89
90 ret = tegra_rpc_open(&info);
91 if (ret < 0)
92 return -ENOMEM;
93
94 nonseekable_open(inode, file);
95 file->private_data = info;
96 return 0;
97}
98
99int tegra_rpc_release(struct tegra_rpc_info *info)
100{
101 if (info->rpc_ep)
102 trpc_close(info->rpc_ep);
103 if (info->sema)
104 trpc_sema_put(info->sema);
105 kfree(info);
106 return 0;
107}
108EXPORT_SYMBOL(tegra_rpc_release);
109
110static int local_rpc_release(struct inode *inode, struct file *file)
111{
112 struct tegra_rpc_info *info = file->private_data;
113
114 tegra_rpc_release(info);
115 file->private_data = NULL;
116 return 0;
117}
118
119static char uniq_name[] = "aaaaaaaa+";
120static const int uniq_len = sizeof(uniq_name) - 1;
121static DEFINE_MUTEX(uniq_lock);
122
123static void _gen_port_name(char *new_name)
124{
125 int i;
126
127 mutex_lock(&uniq_lock);
128 for (i = 0; i < uniq_len - 1; i++) {
129 ++uniq_name[i];
130 if (uniq_name[i] != 'z')
131 break;
132 uniq_name[i] = 'a';
133 }
134 strlcpy(new_name, uniq_name, TEGRA_RPC_MAX_NAME_LEN);
135 mutex_unlock(&uniq_lock);
136}
137
138static int _validate_port_name(const char *name)
139{
140 int i;
141
142 for (i = 0; i < num_reserved_ports; i++)
143 if (!strncmp(name, reserved_ports[i], TEGRA_RPC_MAX_NAME_LEN))
144 return -EINVAL;
145 return 0;
146}
147
148int tegra_rpc_port_create(struct tegra_rpc_info *info, char *name,
149 struct tegra_sema_info *sema)
150{
151 struct trpc_endpoint *ep;
152 int ret = 0;
153
154 if (info->rpc_ep) {
155 ret = -EINVAL;
156 goto err;
157 }
158
159 name[TEGRA_RPC_MAX_NAME_LEN - 1] = '\0';
160 if (name[0]) {
161 ret = _validate_port_name(name);
162 if (ret)
163 goto err;
164 } else {
165 _gen_port_name(name);
166 }
167 ep = trpc_create(&rpc_node, name, &ep_ops, info);
168 if (IS_ERR(ep)) {
169 ret = PTR_ERR(ep);
170 goto err;
171 }
172 info->rpc_ep = ep;
173 info->sema = sema;
174 return 0;
175
176err:
177 return ret;
178}
179
180int tegra_rpc_get_name(struct tegra_rpc_info *info, char* name)
181{
182 if (!info->rpc_ep)
183 return -EINVAL;
184
185 strcpy(name, trpc_name(info->rpc_ep));
186 return 0;
187}
188
189int tegra_rpc_port_connect(struct tegra_rpc_info *info, long timeout)
190{
191 if (!info->rpc_ep)
192 return -EINVAL;
193
194 return trpc_connect(info->rpc_ep, timeout);
195
196}
197
198int tegra_rpc_port_listen(struct tegra_rpc_info *info, long timeout)
199{
200 if (!info->rpc_ep)
201 return -EINVAL;
202
203 return trpc_wait_peer(info->rpc_ep, timeout);
204}
205
206static long local_rpc_ioctl(struct file *file, unsigned int cmd,
207 unsigned long arg)
208{
209 struct tegra_rpc_info *info = file->private_data;
210 struct tegra_rpc_port_desc desc;
211 struct tegra_sema_info *sema = NULL;
212 int ret = 0;
213
214 if (_IOC_TYPE(cmd) != TEGRA_RPC_IOCTL_MAGIC ||
215 _IOC_NR(cmd) < TEGRA_RPC_IOCTL_MIN_NR ||
216 _IOC_NR(cmd) > TEGRA_RPC_IOCTL_MAX_NR) {
217 ret = -ENOTTY;
218 goto err;
219 }
220
221 switch (cmd) {
222 case TEGRA_RPC_IOCTL_PORT_CREATE:
223
224 if (_IOC_SIZE(cmd) != sizeof(struct tegra_rpc_port_desc))
225 return -EINVAL;
226 if (copy_from_user(&desc, (void __user *)arg, sizeof(desc)))
227 return -EFAULT;
228 if (desc.notify_fd != -1) {
229 sema = trpc_sema_get_from_fd(desc.notify_fd);
230 if (IS_ERR(sema)) {
231 ret = PTR_ERR(sema);
232 goto err;
233 }
234 }
235
236 ret = tegra_rpc_port_create(info, desc.name, sema);
237 if (ret < 0)
238 goto err;
239
240 break;
241 case TEGRA_RPC_IOCTL_PORT_GET_NAME:
242 if (!info->rpc_ep) {
243 ret = -EINVAL;
244 goto err;
245 }
246 if (copy_to_user((void __user *)arg,
247 trpc_name(info->rpc_ep),
248 TEGRA_RPC_MAX_NAME_LEN)) {
249 ret = -EFAULT;
250 goto err;
251 }
252 break;
253 case TEGRA_RPC_IOCTL_PORT_CONNECT:
254 if (!info->rpc_ep) {
255 ret = -EINVAL;
256 goto err;
257 }
258 ret = trpc_connect(info->rpc_ep, (long)arg);
259 if (ret) {
260 pr_err("%s: can't connect to '%s' (%d)\n", __func__,
261 trpc_name(info->rpc_ep), ret);
262 goto err;
263 }
264 break;
265 case TEGRA_RPC_IOCTL_PORT_LISTEN:
266 if (!info->rpc_ep) {
267 ret = -EINVAL;
268 goto err;
269 }
270 ret = trpc_wait_peer(info->rpc_ep, (long)arg);
271 if (ret) {
272 pr_err("%s: error waiting for peer for '%s' (%d)\n",
273 __func__, trpc_name(info->rpc_ep), ret);
274 goto err;
275 }
276 break;
277 default:
278 pr_err("%s: unknown cmd %d\n", __func__, _IOC_NR(cmd));
279 ret = -EINVAL;
280 goto err;
281 }
282
283 return 0;
284
285err:
286 if (ret && ret != -ERESTARTSYS)
287 pr_err("tegra_rpc: pid=%d ioctl=%x/%lx (%x) ret=%d\n",
288 current->pid, cmd, arg, _IOC_NR(cmd), ret);
289 return (long)ret;
290}
291
292int tegra_rpc_write(struct tegra_rpc_info *info, u8* buf, size_t size)
293{
294 int ret;
295
296 if (!info->rpc_ep)
297 return -EINVAL;
298
299 if (TEGRA_RPC_MAX_MSG_LEN < size)
300 return -EINVAL;
301
302 ret = trpc_send_msg(&rpc_node, info->rpc_ep, buf, size,
303 GFP_KERNEL);
304 if (ret)
305 return ret;
306 return size;
307}
308
309static ssize_t local_rpc_write(struct file *file, const char __user *buf,
310 size_t count, loff_t *ppos)
311{
312 struct tegra_rpc_info *info = file->private_data;
313 u8 data[TEGRA_RPC_MAX_MSG_LEN];
314 int ret;
315
316 if (!info)
317 return -EINVAL;
318 else if (count > TEGRA_RPC_MAX_MSG_LEN)
319 return -EINVAL;
320
321 if (copy_from_user(data, buf, count))
322 return -EFAULT;
323
324 ret = trpc_send_msg(&rpc_node, info->rpc_ep, data, count,
325 GFP_KERNEL);
326 if (ret)
327 return ret;
328 return count;
329}
330
331int tegra_rpc_read(struct tegra_rpc_info *info, u8 *buf, size_t max)
332{
333 int ret;
334
335 if (max > TEGRA_RPC_MAX_MSG_LEN)
336 return -EINVAL;
337
338 ret = trpc_recv_msg(&rpc_node, info->rpc_ep, buf,
339 TEGRA_RPC_MAX_MSG_LEN, 0);
340 if (ret == 0)
341 return 0;
342 else if (ret < 0)
343 return ret;
344 else if (ret > max)
345 return -ENOSPC;
346
347 return ret;
348}
349
350static ssize_t local_rpc_read(struct file *file, char __user *buf, size_t max,
351 loff_t *ppos)
352{
353 struct tegra_rpc_info *info = file->private_data;
354 int ret;
355 u8 data[TEGRA_RPC_MAX_MSG_LEN];
356
357 if (max > TEGRA_RPC_MAX_MSG_LEN)
358 return -EINVAL;
359
360 ret = trpc_recv_msg(&rpc_node, info->rpc_ep, data,
361 TEGRA_RPC_MAX_MSG_LEN, 0);
362 if (ret == 0)
363 return 0;
364 else if (ret < 0)
365 return ret;
366 else if (ret > max)
367 return -ENOSPC;
368 else if (copy_to_user(buf, data, ret))
369 return -EFAULT;
370
371 return ret;
372}
373
374static const struct file_operations local_rpc_misc_fops = {
375 .owner = THIS_MODULE,
376 .open = local_rpc_open,
377 .release = local_rpc_release,
378 .unlocked_ioctl = local_rpc_ioctl,
379 .write = local_rpc_write,
380 .read = local_rpc_read,
381};
382
383static struct miscdevice local_rpc_misc_device = {
384 .minor = MISC_DYNAMIC_MINOR,
385 .name = "tegra_rpc",
386 .fops = &local_rpc_misc_fops,
387};
388
389int __init rpc_local_init(void)
390{
391 int ret;
392
393 ret = trpc_sema_init();
394 if (ret) {
395 pr_err("%s: error in trpc_sema_init\n", __func__);
396 goto err_sema_init;
397 }
398
399 ret = misc_register(&local_rpc_misc_device);
400 if (ret) {
401 pr_err("%s: can't register misc device\n", __func__);
402 goto err_misc;
403 }
404
405 ret = trpc_node_register(&rpc_node);
406 if (ret) {
407 pr_err("%s: can't register rpc node\n", __func__);
408 goto err_node_reg;
409 }
410 return 0;
411
412err_node_reg:
413 misc_deregister(&local_rpc_misc_device);
414err_misc:
415err_sema_init:
416 return ret;
417}
418
419module_init(rpc_local_init);
diff --git a/drivers/media/video/tegra/avp/trpc_sema.c b/drivers/media/video/tegra/avp/trpc_sema.c
new file mode 100644
index 00000000000..cd717a1a0ca
--- /dev/null
+++ b/drivers/media/video/tegra/avp/trpc_sema.c
@@ -0,0 +1,244 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 *
4 * Author:
5 * Dima Zavin <dima@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/err.h>
19#include <linux/file.h>
20#include <linux/fs.h>
21#include <linux/miscdevice.h>
22#include <linux/sched.h>
23#include <linux/slab.h>
24#include <linux/spinlock.h>
25#include <linux/tegra_sema.h>
26#include <linux/types.h>
27#include <linux/uaccess.h>
28#include <linux/wait.h>
29
30#include "trpc_sema.h"
31
32struct tegra_sema_info {
33 struct file *file;
34 wait_queue_head_t wq;
35 spinlock_t lock;
36 int count;
37};
38
39static int rpc_sema_minor = -1;
40
41static inline bool is_trpc_sema_file(struct file *file)
42{
43 dev_t rdev = file->f_dentry->d_inode->i_rdev;
44
45 if (MAJOR(rdev) == MISC_MAJOR && MINOR(rdev) == rpc_sema_minor)
46 return true;
47 return false;
48}
49
50struct tegra_sema_info *trpc_sema_get_from_fd(int fd)
51{
52 struct file *file;
53
54 file = fget(fd);
55 if (unlikely(file == NULL)) {
56 pr_err("%s: fd %d is invalid\n", __func__, fd);
57 return ERR_PTR(-EINVAL);
58 }
59
60 if (!is_trpc_sema_file(file)) {
61 pr_err("%s: fd (%d) is not a trpc_sema file\n", __func__, fd);
62 fput(file);
63 return ERR_PTR(-EINVAL);
64 }
65
66 return file->private_data;
67}
68
69void trpc_sema_put(struct tegra_sema_info *info)
70{
71 if (info->file)
72 fput(info->file);
73}
74
75int tegra_sema_signal(struct tegra_sema_info *info)
76{
77 unsigned long flags;
78
79 if (!info)
80 return -EINVAL;
81
82 spin_lock_irqsave(&info->lock, flags);
83 info->count++;
84 wake_up_interruptible_all(&info->wq);
85 spin_unlock_irqrestore(&info->lock, flags);
86 return 0;
87}
88
89int tegra_sema_wait(struct tegra_sema_info *info, long *timeout)
90{
91 unsigned long flags;
92 int ret = 0;
93 unsigned long endtime;
94 long timeleft = *timeout;
95
96 *timeout = 0;
97 if (timeleft < 0)
98 timeleft = MAX_SCHEDULE_TIMEOUT;
99
100 timeleft = msecs_to_jiffies(timeleft);
101 endtime = jiffies + timeleft;
102
103again:
104 if (timeleft)
105 ret = wait_event_interruptible_timeout(info->wq,
106 info->count > 0,
107 timeleft);
108 spin_lock_irqsave(&info->lock, flags);
109 if (info->count > 0) {
110 info->count--;
111 ret = 0;
112 } else if (ret == 0 || timeout == 0) {
113 ret = -ETIMEDOUT;
114 } else if (ret < 0) {
115 ret = -EINTR;
116 if (timeleft != MAX_SCHEDULE_TIMEOUT &&
117 time_before(jiffies, endtime))
118 *timeout = jiffies_to_msecs(endtime - jiffies);
119 else
120 *timeout = 0;
121 } else {
122 /* we woke up but someone else got the semaphore and we have
123 * time left, try again */
124 timeleft = ret;
125 spin_unlock_irqrestore(&info->lock, flags);
126 goto again;
127 }
128 spin_unlock_irqrestore(&info->lock, flags);
129 return ret;
130}
131
132int tegra_sema_open(struct tegra_sema_info **sema)
133{
134 struct tegra_sema_info *info;
135 info = kzalloc(sizeof(struct tegra_sema_info), GFP_KERNEL);
136 if (!info)
137 return -ENOMEM;
138
139 init_waitqueue_head(&info->wq);
140 spin_lock_init(&info->lock);
141 *sema = info;
142 return 0;
143}
144
145static int trpc_sema_open(struct inode *inode, struct file *file)
146{
147 struct tegra_sema_info *info;
148 int ret;
149
150 ret = tegra_sema_open(&info);
151 if (ret < 0)
152 return ret;
153
154 info->file = file;
155 nonseekable_open(inode, file);
156 file->private_data = info;
157 return 0;
158}
159
160int tegra_sema_release(struct tegra_sema_info *sema)
161{
162 kfree(sema);
163 return 0;
164}
165
166static int trpc_sema_release(struct inode *inode, struct file *file)
167{
168 struct tegra_sema_info *info = file->private_data;
169
170 file->private_data = NULL;
171 tegra_sema_release(info);
172 return 0;
173}
174
175static long trpc_sema_ioctl(struct file *file, unsigned int cmd,
176 unsigned long arg)
177{
178 struct tegra_sema_info *info = file->private_data;
179 int ret;
180 long timeout;
181
182 if (_IOC_TYPE(cmd) != TEGRA_SEMA_IOCTL_MAGIC ||
183 _IOC_NR(cmd) < TEGRA_SEMA_IOCTL_MIN_NR ||
184 _IOC_NR(cmd) > TEGRA_SEMA_IOCTL_MAX_NR)
185 return -ENOTTY;
186 else if (!info)
187 return -EINVAL;
188
189 switch (cmd) {
190 case TEGRA_SEMA_IOCTL_WAIT:
191 if (copy_from_user(&timeout, (void __user *)arg, sizeof(long)))
192 return -EFAULT;
193 ret = tegra_sema_wait(info, &timeout);
194 if (ret != -EINTR)
195 break;
196 if (copy_to_user((void __user *)arg, &timeout, sizeof(long)))
197 ret = -EFAULT;
198 break;
199 case TEGRA_SEMA_IOCTL_SIGNAL:
200 ret = tegra_sema_signal(info);
201 break;
202 default:
203 pr_err("%s: Unknown tegra_sema ioctl 0x%x\n", __func__,
204 _IOC_NR(cmd));
205 ret = -ENOTTY;
206 break;
207 }
208 return ret;
209}
210
211static const struct file_operations trpc_sema_misc_fops = {
212 .owner = THIS_MODULE,
213 .open = trpc_sema_open,
214 .release = trpc_sema_release,
215 .unlocked_ioctl = trpc_sema_ioctl,
216};
217
218static struct miscdevice trpc_sema_misc_device = {
219 .minor = MISC_DYNAMIC_MINOR,
220 .name = "tegra_sema",
221 .fops = &trpc_sema_misc_fops,
222};
223
224int __init trpc_sema_init(void)
225{
226 int ret;
227
228 if (rpc_sema_minor >= 0) {
229 pr_err("%s: trpc_sema already registered\n", __func__);
230 return -EBUSY;
231 }
232
233 ret = misc_register(&trpc_sema_misc_device);
234 if (ret) {
235 pr_err("%s: can't register misc device\n", __func__);
236 return ret;
237 }
238
239 rpc_sema_minor = trpc_sema_misc_device.minor;
240 pr_info("%s: registered misc dev %d:%d\n", __func__, MISC_MAJOR,
241 rpc_sema_minor);
242
243 return 0;
244}
diff --git a/drivers/media/video/tegra/avp/trpc_sema.h b/drivers/media/video/tegra/avp/trpc_sema.h
new file mode 100644
index 00000000000..2a7c42245b7
--- /dev/null
+++ b/drivers/media/video/tegra/avp/trpc_sema.h
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 *
4 * Author:
5 * Dima Zavin <dima@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#ifndef __ARM_MACH_TEGRA_RPC_SEMA_H
19#define __ARM_MACH_TEGRA_RPC_SEMA_H
20
21#include <linux/types.h>
22#include <linux/fs.h>
23
24struct tegra_sema_info;
25
26struct tegra_sema_info *trpc_sema_get_from_fd(int fd);
27void trpc_sema_put(struct tegra_sema_info *sema);
28int __init trpc_sema_init(void);
29
30#endif
diff --git a/drivers/media/video/tegra/mediaserver/Kconfig b/drivers/media/video/tegra/mediaserver/Kconfig
new file mode 100644
index 00000000000..9e60a5b49cd
--- /dev/null
+++ b/drivers/media/video/tegra/mediaserver/Kconfig
@@ -0,0 +1,10 @@
1config TEGRA_MEDIASERVER
2bool "Tegra Media Server support"
3depends on ARCH_TEGRA && TEGRA_RPC
4default y
5help
6 Enables support for the multiple OpenMAX clients. Exports the
7 interface on the device node /dev/tegra_mediaserver.
8
9 If unsure, say Y
10
diff --git a/drivers/media/video/tegra/mediaserver/Makefile b/drivers/media/video/tegra/mediaserver/Makefile
new file mode 100644
index 00000000000..ed24e91932b
--- /dev/null
+++ b/drivers/media/video/tegra/mediaserver/Makefile
@@ -0,0 +1,3 @@
1GCOV_PROFILE := y
2obj-$(CONFIG_TEGRA_MEDIASERVER) += tegra_mediaserver.o
3
diff --git a/drivers/media/video/tegra/mediaserver/tegra_mediaserver.c b/drivers/media/video/tegra/mediaserver/tegra_mediaserver.c
new file mode 100644
index 00000000000..f6f5b1ec8b7
--- /dev/null
+++ b/drivers/media/video/tegra/mediaserver/tegra_mediaserver.c
@@ -0,0 +1,556 @@
1/*
2 * Copyright (C) 2011 NVIDIA Corp.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/fs.h>
18#include <linux/miscdevice.h>
19#include <linux/slab.h>
20#include <linux/uaccess.h>
21#include <linux/mm.h>
22
23#include <linux/tegra_mediaserver.h>
24#include "../avp/nvavp.h"
25#include "../../../../video/tegra/nvmap/nvmap.h"
26
27#define CHECK_STATUS(e, tag) \
28 do { if (e < 0) goto tag; } while (0)
29
30#define CHECK_NULL(ptr, tag) \
31 do { if (!ptr) goto tag; } while (0)
32
33#define CHECK_CONDITION(c, tag) \
34 do { if (c) goto tag; } while (0)
35
36struct tegra_mediasrv_block {
37 struct list_head entry;
38 struct tegra_mediaserver_block_info block;
39};
40
41struct tegra_mediasrv_iram {
42 struct list_head entry;
43 struct tegra_mediaserver_iram_info iram;
44};
45
46struct tegra_mediasrv_node {
47 struct tegra_mediasrv_info *mediasrv;
48 struct list_head blocks;
49 int nr_iram_shared;
50};
51
52struct tegra_mediasrv_manager {
53 struct tegra_avp_lib lib;
54 struct tegra_rpc_info *rpc;
55 struct tegra_sema_info *sema;
56};
57
58struct tegra_mediasrv_info {
59 int minor;
60 struct mutex lock;
61 struct nvmap_client *nvmap;
62 struct tegra_avp_info *avp;
63 struct tegra_mediasrv_manager manager;
64 int nr_nodes;
65 int nr_blocks;
66 struct tegra_mediaserver_iram_info iram; /* only one supported */
67 int nr_iram_shared;
68};
69
70static struct tegra_mediasrv_info *mediasrv_info;
71
72
73/*
74 * File entry points
75 */
76static int mediasrv_open(struct inode *inode, struct file *file)
77{
78 struct tegra_mediasrv_info *mediasrv = mediasrv_info;
79 struct tegra_mediasrv_node *node = NULL;
80 struct tegra_mediasrv_manager *manager = &mediasrv->manager;
81 struct tegra_avp_lib *lib = &manager->lib;
82 int e;
83
84 node = kzalloc(sizeof(struct tegra_mediasrv_node), GFP_KERNEL);
85 CHECK_NULL(node, node_alloc_fail);
86 INIT_LIST_HEAD(&node->blocks);
87 node->mediasrv = mediasrv;
88
89 mutex_lock(&mediasrv->lock);
90 nonseekable_open(inode, file);
91
92 if (!mediasrv->nr_nodes) {
93 e = tegra_sema_open(&manager->sema);
94 CHECK_STATUS(e, fail);
95
96 e = tegra_rpc_open(&manager->rpc);
97 CHECK_STATUS(e, fail);
98
99 e = tegra_rpc_port_create(manager->rpc, "NVMM_MANAGER_SRV",
100 manager->sema);
101 CHECK_STATUS(e, fail);
102
103 e = tegra_avp_open(&mediasrv->avp);
104 CHECK_STATUS(e, fail);
105
106 memcpy(lib->name, "nvmm_manager.axf\0",
107 strlen("nvmm_manager.axf") + 1);
108 lib->args = &mediasrv;
109 lib->args_len = sizeof(unsigned long);
110 e = tegra_avp_load_lib(mediasrv->avp, lib);
111 CHECK_STATUS(e, fail);
112
113 e = tegra_rpc_port_connect(manager->rpc, 50000);
114 CHECK_STATUS(e, fail);
115 }
116
117 mediasrv->nr_nodes++;
118 try_module_get(THIS_MODULE);
119
120 mutex_unlock(&mediasrv->lock);
121
122 file->private_data = node;
123
124 return 0;
125
126fail:
127 if (lib->handle) {
128 tegra_avp_unload_lib(mediasrv->avp, lib->handle);
129 lib->handle = 0;
130 }
131
132 if (mediasrv->avp) {
133 tegra_avp_release(mediasrv->avp);
134 mediasrv->avp = NULL;
135 }
136
137 if (manager->rpc) {
138 tegra_rpc_release(manager->rpc);
139 manager->rpc = NULL;
140 }
141 if (manager->sema) {
142 tegra_sema_release(manager->sema);
143 manager->sema = NULL;
144 }
145
146 kfree(node);
147
148 mutex_unlock(&mediasrv->lock);
149 return e;
150
151node_alloc_fail:
152 e = -ENOMEM;
153 return e;
154}
155
156static int mediasrv_release(struct inode *inode, struct file *file)
157{
158 struct tegra_mediasrv_info *mediasrv = mediasrv_info;
159 struct tegra_mediasrv_node *node = file->private_data;
160 struct tegra_mediasrv_block *block;
161 struct list_head *entry;
162 struct list_head *temp;
163 u32 message[2];
164 int e;
165
166 mutex_lock(&mediasrv->lock);
167
168 list_for_each_safe(entry, temp, &node->blocks) {
169 block = list_entry(entry, struct tegra_mediasrv_block, entry);
170
171 pr_info("Improperly closed block found!");
172 pr_info(" NVMM Block Handle: 0x%08x\n",
173 block->block.nvmm_block_handle);
174 pr_info(" AVP Block Handle: 0x%08x\n",
175 block->block.avp_block_handle);
176
177 message[0] = 1; /* NvmmManagerMsgType_AbnormalTerm */
178 message[1] = block->block.avp_block_handle;
179
180 e = tegra_rpc_write(mediasrv->manager.rpc, (u8 *)message,
181 sizeof(u32) * 2);
182 pr_info("Abnormal termination message result: %d\n", e);
183
184 if (block->block.avp_block_library_handle) {
185 e = tegra_avp_unload_lib(mediasrv->avp,
186 block->block.avp_block_library_handle);
187 pr_info("Unload block (0x%08x) result: %d\n",
188 block->block.avp_block_library_handle, e);
189 }
190
191 if (block->block.service_library_handle) {
192 e = tegra_avp_unload_lib(mediasrv->avp,
193 block->block.service_library_handle);
194 pr_info("Unload service (0x%08x) result: %d\n",
195 block->block.service_library_handle, e);
196 }
197
198 mediasrv->nr_blocks--;
199 list_del(entry);
200 kfree(block);
201 }
202
203 mediasrv->nr_iram_shared -= node->nr_iram_shared;
204 if (mediasrv->iram.rm_handle && !mediasrv->nr_iram_shared) {
205 pr_info("Improperly freed shared iram found!");
206 nvmap_unpin_ids(mediasrv->nvmap, 1, &mediasrv->iram.rm_handle);
207 nvmap_free_handle_id(mediasrv->nvmap, mediasrv->iram.rm_handle);
208 mediasrv->iram.rm_handle = 0;
209 mediasrv->iram.physical_address = 0;
210 }
211
212 kfree(node);
213 mediasrv->nr_nodes--;
214 if (!mediasrv->nr_nodes) {
215 struct tegra_mediasrv_manager *manager = &mediasrv->manager;
216
217 tegra_avp_unload_lib(mediasrv->avp, manager->lib.handle);
218 manager->lib.handle = 0;
219
220 tegra_avp_release(mediasrv->avp);
221 mediasrv->avp = NULL;
222
223 tegra_rpc_release(manager->rpc);
224 manager->rpc = NULL;
225
226 tegra_sema_release(manager->sema);
227 manager->sema = NULL;
228 }
229
230 mutex_unlock(&mediasrv->lock);
231 module_put(THIS_MODULE);
232 return 0;
233}
234
235static int mediasrv_alloc(struct tegra_mediasrv_node *node,
236 union tegra_mediaserver_alloc_info *in,
237 union tegra_mediaserver_alloc_info *out)
238{
239 struct tegra_mediasrv_info *mediasrv = node->mediasrv;
240 int e;
241
242 switch (in->in.tegra_mediaserver_resource_type) {
243 case TEGRA_MEDIASERVER_RESOURCE_BLOCK:
244 {
245 struct tegra_mediasrv_block *block;
246
247 block = kzalloc(sizeof(struct tegra_mediasrv_block),
248 GFP_KERNEL);
249 CHECK_NULL(block, block_alloc_fail);
250
251 block->block = in->in.u.block;
252 list_add(&block->entry, &node->blocks);
253 goto block_done;
254
255block_alloc_fail:
256 e = -ENOMEM;
257 goto fail;
258
259block_done:
260 mediasrv->nr_blocks++;
261 out->out.u.block.count = mediasrv->nr_blocks;
262 }
263 break;
264
265 case TEGRA_MEDIASERVER_RESOURCE_IRAM:
266 {
267 if (in->in.u.iram.tegra_mediaserver_iram_type ==
268 TEGRA_MEDIASERVER_IRAM_SHARED) {
269 if (!mediasrv->nr_iram_shared) {
270 size_t align, size;
271 struct nvmap_handle_ref *r = NULL;
272 unsigned long id;
273 int physical_address;
274
275 size = PAGE_ALIGN(in->in.u.iram.size);
276 r = nvmap_create_handle(mediasrv->nvmap, size);
277 CHECK_CONDITION((r < 0),
278 iram_shared_handle_fail);
279
280 id = nvmap_ref_to_id(r);
281
282 align = max_t(size_t, in->in.u.iram.alignment,
283 PAGE_SIZE);
284 e = nvmap_alloc_handle_id(mediasrv->nvmap, id,
285 NVMAP_HEAP_CARVEOUT_IRAM, align,
286 NVMAP_HANDLE_WRITE_COMBINE);
287 CHECK_STATUS(e, iram_shared_alloc_fail);
288
289 physical_address =
290 nvmap_pin_ids(mediasrv->nvmap, 1, &id);
291 CHECK_CONDITION((physical_address < 0),
292 iram_shared_pin_fail);
293
294 mediasrv->iram.rm_handle = id;
295 mediasrv->iram.physical_address =
296 physical_address;
297 goto iram_shared_done;
298
299iram_shared_pin_fail:
300 e = physical_address;
301iram_shared_alloc_fail:
302 nvmap_free_handle_id(mediasrv->nvmap, id);
303iram_shared_handle_fail:
304 goto fail;
305 }
306
307iram_shared_done:
308 out->out.u.iram.rm_handle = mediasrv->iram.rm_handle;
309 out->out.u.iram.physical_address =
310 mediasrv->iram.physical_address;
311 mediasrv->nr_iram_shared++;
312 node->nr_iram_shared++;
313 } else if (in->in.u.iram.tegra_mediaserver_iram_type ==
314 TEGRA_MEDIASERVER_IRAM_SCRATCH) {
315 e = -EINVAL;
316 goto fail;
317 }
318 }
319 break;
320
321 default:
322 {
323 e = -EINVAL;
324 goto fail;
325 }
326 break;
327 }
328
329 return 0;
330
331fail:
332 return e;
333}
334
335static void mediasrv_free(struct tegra_mediasrv_node *node,
336 union tegra_mediaserver_free_info *in)
337{
338 struct tegra_mediasrv_info *mediasrv = node->mediasrv;
339
340 switch (in->in.tegra_mediaserver_resource_type) {
341 case TEGRA_MEDIASERVER_RESOURCE_BLOCK:
342 {
343 struct tegra_mediasrv_block *block = NULL;
344 struct tegra_mediasrv_block *temp;
345 struct list_head *entry;
346
347 list_for_each(entry, &node->blocks) {
348 temp = list_entry(entry, struct tegra_mediasrv_block,
349 entry);
350 if (temp->block.nvmm_block_handle !=
351 in->in.u.nvmm_block_handle)
352 continue;
353
354 block = temp;
355 break;
356 }
357
358 CHECK_NULL(block, done);
359 list_del(&block->entry);
360 kfree(block);
361 }
362 break;
363
364 case TEGRA_MEDIASERVER_RESOURCE_IRAM:
365 {
366 if (in->in.u.iram_rm_handle == mediasrv->iram.rm_handle &&
367 node->nr_iram_shared) {
368 node->nr_iram_shared--;
369 mediasrv->nr_iram_shared--;
370
371 if (!mediasrv->nr_iram_shared) {
372 nvmap_unpin_ids(mediasrv->nvmap, 1,
373 &mediasrv->iram.rm_handle);
374 nvmap_free_handle_id(mediasrv->nvmap,
375 mediasrv->iram.rm_handle);
376 mediasrv->iram.rm_handle = 0;
377 mediasrv->iram.physical_address = 0;
378 }
379 }
380
381 else
382 goto done;
383 }
384 break;
385 }
386
387done:
388 return;
389}
390
391static int mediasrv_update_block_info(
392 struct tegra_mediasrv_node *node,
393 union tegra_mediaserver_update_block_info *in
394)
395{
396 struct tegra_mediasrv_block *entry = NULL;
397 struct tegra_mediasrv_block *block = NULL;
398 int e;
399
400 list_for_each_entry(entry, &node->blocks, entry) {
401 if (entry->block.nvmm_block_handle != in->in.nvmm_block_handle)
402 continue;
403
404 block = entry;
405 break;
406 }
407
408 CHECK_NULL(block, fail);
409
410 block->block = in->in;
411 return 0;
412
413fail:
414 e = -EINVAL;
415 return e;
416}
417
418static long mediasrv_unlocked_ioctl(struct file *file, unsigned int cmd,
419 unsigned long arg)
420{
421 struct tegra_mediasrv_info *mediasrv = mediasrv_info;
422 struct tegra_mediasrv_node *node = file->private_data;
423 int e = -ENODEV;
424
425 mutex_lock(&mediasrv->lock);
426
427 switch (cmd) {
428 case TEGRA_MEDIASERVER_IOCTL_ALLOC:
429 {
430 union tegra_mediaserver_alloc_info in, out;
431 e = copy_from_user(&in, (void __user *)arg, sizeof(in));
432 CHECK_CONDITION(e, copy_fail);
433 e = mediasrv_alloc(node, &in, &out);
434 CHECK_STATUS(e, fail);
435 e = copy_to_user((void __user *)arg, &out, sizeof(out));
436 CHECK_CONDITION(e, copy_fail);
437 }
438 break;
439
440 case TEGRA_MEDIASERVER_IOCTL_FREE:
441 {
442 union tegra_mediaserver_free_info in;
443 e = copy_from_user(&in, (void __user *)arg, sizeof(in));
444 CHECK_CONDITION(e, copy_fail);
445 mediasrv_free(node, &in);
446 }
447 break;
448
449 case TEGRA_MEDIASERVER_IOCTL_UPDATE_BLOCK_INFO:
450 {
451 union tegra_mediaserver_update_block_info in;
452 e = copy_from_user(&in, (void __user *)arg, sizeof(in));
453 CHECK_CONDITION(e, copy_fail);
454 e = mediasrv_update_block_info(node, &in);
455 CHECK_CONDITION(e, fail);
456 }
457 break;
458
459 default:
460 {
461 e = -ENODEV;
462 goto fail;
463 }
464 break;
465 }
466
467 mutex_unlock(&mediasrv->lock);
468 return 0;
469
470copy_fail:
471 e = -EFAULT;
472fail:
473 mutex_unlock(&mediasrv->lock);
474 return e;
475}
476
477/*
478 * Kernel structures and entry points
479 */
480static const struct file_operations mediaserver_fops = {
481 .owner = THIS_MODULE,
482 .open = mediasrv_open,
483 .release = mediasrv_release,
484 .unlocked_ioctl = mediasrv_unlocked_ioctl,
485};
486
487static struct miscdevice mediaserver_misc_device = {
488 .minor = MISC_DYNAMIC_MINOR,
489 .name = "tegra_mediaserver",
490 .fops = &mediaserver_fops,
491};
492
493static int __init tegra_mediaserver_init(void)
494{
495 struct tegra_mediasrv_info *mediasrv;
496 int e = 0;
497
498 CHECK_NULL(!mediasrv_info, busy);
499
500 mediasrv = kzalloc(sizeof(struct tegra_mediasrv_info), GFP_KERNEL);
501 CHECK_NULL(mediasrv, alloc_fail);
502
503 mediasrv->nvmap = nvmap_create_client(nvmap_dev, "tegra_mediaserver");
504 CHECK_NULL(mediasrv, nvmap_create_fail);
505
506 e = misc_register(&mediaserver_misc_device);
507 CHECK_STATUS(e, register_fail);
508
509 mediasrv->nr_nodes = 0;
510 mutex_init(&mediasrv->lock);
511
512 mediasrv_info = mediasrv;
513 goto done;
514
515nvmap_create_fail:
516 e = -ENOMEM;
517 kfree(mediasrv);
518 goto done;
519
520register_fail:
521 nvmap_client_put(mediasrv->nvmap);
522 kfree(mediasrv);
523 goto done;
524
525alloc_fail:
526 e = -ENOMEM;
527 goto done;
528
529busy:
530 e = -EBUSY;
531 goto done;
532
533done:
534 return e;
535}
536
537void __exit tegra_mediaserver_cleanup(void)
538{
539 struct tegra_mediasrv_info *mediasrv = mediasrv_info;
540 int e;
541
542 e = misc_deregister(&mediaserver_misc_device);
543 CHECK_STATUS(e, fail);
544
545 nvmap_client_put(mediasrv->nvmap);
546 kfree(mediasrv);
547 mediasrv_info = NULL;
548
549fail:
550 return;
551}
552
553module_init(tegra_mediaserver_init);
554module_exit(tegra_mediaserver_cleanup);
555MODULE_LICENSE("GPL");
556
diff --git a/drivers/media/video/tegra/nvavp/Kconfig b/drivers/media/video/tegra/nvavp/Kconfig
new file mode 100644
index 00000000000..2d3af3f79fb
--- /dev/null
+++ b/drivers/media/video/tegra/nvavp/Kconfig
@@ -0,0 +1,10 @@
1config TEGRA_NVAVP
2 bool "Enable support for Tegra NVAVP driver"
3 depends on ARCH_TEGRA && TEGRA_GRHOST
4 default n
5 help
6 Enables support for the push-buffer mechanism based driver for the Tegra
7 multimedia framework. Exports the Tegra nvavp interface on device node
8 /dev/tegra_avpchannel.
9
10 If unsure, say N
diff --git a/drivers/media/video/tegra/nvavp/Makefile b/drivers/media/video/tegra/nvavp/Makefile
new file mode 100644
index 00000000000..82b4238fd08
--- /dev/null
+++ b/drivers/media/video/tegra/nvavp/Makefile
@@ -0,0 +1,3 @@
1GCOV_PROFILE := y
2obj-$(CONFIG_TEGRA_NVAVP) += nvavp_dev.o
3obj-$(CONFIG_TEGRA_AVP_KERNEL_ON_MMU) += ../avp/headavp.o
diff --git a/drivers/media/video/tegra/nvavp/nvavp_dev.c b/drivers/media/video/tegra/nvavp/nvavp_dev.c
new file mode 100644
index 00000000000..407e35b40c4
--- /dev/null
+++ b/drivers/media/video/tegra/nvavp/nvavp_dev.c
@@ -0,0 +1,1441 @@
1/*
2 * drivers/media/video/tegra/nvavp/nvavp_dev.c
3 *
4 * Copyright (C) 2011-2012 NVIDIA Corp.
5 *
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
9 */
10
11#include <linux/uaccess.h>
12#include <linux/clk.h>
13#include <linux/completion.h>
14#include <linux/delay.h>
15#include <linux/dma-mapping.h>
16#include <linux/err.h>
17#include <linux/firmware.h>
18#include <linux/fs.h>
19#include <linux/interrupt.h>
20#include <linux/io.h>
21#include <linux/ioctl.h>
22#include <linux/irq.h>
23#include <linux/kref.h>
24#include <linux/list.h>
25#include <linux/miscdevice.h>
26#include <linux/mutex.h>
27#include <linux/nvhost.h>
28#include <linux/platform_device.h>
29#include <linux/rbtree.h>
30#include <linux/seq_file.h>
31#include <linux/slab.h>
32#include <linux/string.h>
33#include <linux/tegra_nvavp.h>
34#include <linux/types.h>
35#include <linux/vmalloc.h>
36#include <linux/workqueue.h>
37
38#include <mach/clk.h>
39#include <mach/hardware.h>
40#include <mach/io.h>
41#include <mach/iomap.h>
42#include <mach/legacy_irq.h>
43#include <mach/nvmap.h>
44
45#include "../../../../video/tegra/nvmap/nvmap.h"
46#include "../../../../video/tegra/host/host1x/host1x_syncpt.h"
47#include "../../../../video/tegra/host/dev.h"
48#include "../../../../video/tegra/host/nvhost_acm.h"
49
50#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU)
51#include "../avp/headavp.h"
52#endif
53#include "nvavp_os.h"
54
55#define TEGRA_NVAVP_NAME "nvavp"
56
57#define NVAVP_PUSHBUFFER_SIZE 4096
58
59#define NVAVP_PUSHBUFFER_MIN_UPDATE_SPACE (sizeof(u32) * 3)
60
61#define TEGRA_NVAVP_RESET_VECTOR_ADDR \
62 (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x200)
63
64#define FLOW_CTRL_HALT_COP_EVENTS IO_ADDRESS(TEGRA_FLOW_CTRL_BASE + 0x4)
65#define FLOW_MODE_STOP (0x2 << 29)
66#define FLOW_MODE_NONE 0x0
67
68#define NVAVP_OS_INBOX IO_ADDRESS(TEGRA_RES_SEMA_BASE + 0x10)
69#define NVAVP_OS_OUTBOX IO_ADDRESS(TEGRA_RES_SEMA_BASE + 0x20)
70
71#define NVAVP_INBOX_VALID (1 << 29)
72
73/* AVP behavior params */
74#define NVAVP_OS_IDLE_TIMEOUT 100 /* milli-seconds */
75
76struct nvavp_info {
77 u32 clk_enabled;
78 struct clk *bsev_clk;
79 struct clk *vde_clk;
80 struct clk *cop_clk;
81
82 /* used for dvfs */
83 struct clk *sclk;
84 struct clk *emc_clk;
85 unsigned long sclk_rate;
86 unsigned long emc_clk_rate;
87
88 int mbox_from_avp_pend_irq;
89
90 struct mutex open_lock;
91 int refcount;
92 int initialized;
93
94 struct work_struct clock_disable_work;
95
96 /* os information */
97 struct nvavp_os_info os_info;
98
99 /* ucode information */
100 struct nvavp_ucode_info ucode_info;
101
102 /* client for driver allocations, persistent */
103 struct nvmap_client *nvmap;
104
105 struct mutex pushbuffer_lock;
106 struct nvmap_handle_ref *pushbuf_handle;
107 unsigned long pushbuf_phys;
108 u8 *pushbuf_data;
109 u32 pushbuf_index;
110 u32 pushbuf_fence;
111
112 struct nv_e276_control *os_control;
113
114 struct nvhost_syncpt *nvhost_syncpt;
115 u32 syncpt_id;
116 u32 syncpt_value;
117
118 struct nvhost_device *nvhost_dev;
119 struct miscdevice misc_dev;
120};
121
122struct nvavp_clientctx {
123 struct nvmap_client *nvmap;
124 struct nvavp_pushbuffer_submit_hdr submit_hdr;
125 struct nvavp_reloc relocs[NVAVP_MAX_RELOCATION_COUNT];
126 struct nvmap_handle_ref *gather_mem;
127 int num_relocs;
128 struct nvavp_info *nvavp;
129};
130
131static struct clk *nvavp_clk_get(struct nvavp_info *nvavp, int id)
132{
133 if (!nvavp)
134 return NULL;
135
136 if (id == NVAVP_MODULE_ID_AVP)
137 return nvavp->sclk;
138 if (id == NVAVP_MODULE_ID_VDE)
139 return nvavp->vde_clk;
140 if (id == NVAVP_MODULE_ID_EMC)
141 return nvavp->emc_clk;
142
143 return NULL;
144}
145
146static void nvavp_clk_ctrl(struct nvavp_info *nvavp, u32 clk_en)
147{
148 if (clk_en && !nvavp->clk_enabled) {
149 nvhost_module_busy(nvhost_get_host(nvavp->nvhost_dev)->dev);
150 clk_enable(nvavp->bsev_clk);
151 clk_enable(nvavp->vde_clk);
152 clk_set_rate(nvavp->emc_clk, nvavp->emc_clk_rate);
153 clk_set_rate(nvavp->sclk, nvavp->sclk_rate);
154 nvavp->clk_enabled = 1;
155 dev_dbg(&nvavp->nvhost_dev->dev, "%s: setting sclk to %lu\n",
156 __func__, nvavp->sclk_rate);
157 dev_dbg(&nvavp->nvhost_dev->dev, "%s: setting emc_clk to %lu\n",
158 __func__, nvavp->emc_clk_rate);
159 } else if (!clk_en && nvavp->clk_enabled) {
160 clk_disable(nvavp->bsev_clk);
161 clk_disable(nvavp->vde_clk);
162 clk_set_rate(nvavp->emc_clk, 0);
163 clk_set_rate(nvavp->sclk, 0);
164 nvhost_module_idle(nvhost_get_host(nvavp->nvhost_dev)->dev);
165 nvavp->clk_enabled = 0;
166 dev_dbg(&nvavp->nvhost_dev->dev, "%s: resetting emc_clk "
167 "and sclk\n", __func__);
168 }
169}
170
171static u32 nvavp_check_idle(struct nvavp_info *nvavp)
172{
173 struct nv_e276_control *control = nvavp->os_control;
174 return (control->put == control->get) ? 1 : 0;
175}
176
177static void clock_disable_handler(struct work_struct *work)
178{
179 struct nvavp_info *nvavp;
180
181 nvavp = container_of(work, struct nvavp_info,
182 clock_disable_work);
183
184 mutex_lock(&nvavp->pushbuffer_lock);
185 nvavp_clk_ctrl(nvavp, !nvavp_check_idle(nvavp));
186 mutex_unlock(&nvavp->pushbuffer_lock);
187}
188
189static int nvavp_service(struct nvavp_info *nvavp)
190{
191 struct nvavp_os_info *os = &nvavp->os_info;
192 u8 *debug_print;
193 u32 inbox;
194
195 inbox = readl(NVAVP_OS_INBOX);
196 if (!(inbox & NVAVP_INBOX_VALID))
197 inbox = 0x00000000;
198
199 writel(0x00000000, NVAVP_OS_INBOX);
200
201 if (inbox & NVE276_OS_INTERRUPT_VIDEO_IDLE)
202 schedule_work(&nvavp->clock_disable_work);
203
204 if (inbox & NVE276_OS_INTERRUPT_DEBUG_STRING) {
205 /* Should only occur with debug AVP OS builds */
206 debug_print = os->data;
207 debug_print += os->debug_offset;
208 dev_info(&nvavp->nvhost_dev->dev, "%s\n", debug_print);
209 }
210 if (inbox & (NVE276_OS_INTERRUPT_SEMAPHORE_AWAKEN |
211 NVE276_OS_INTERRUPT_EXECUTE_AWAKEN)) {
212 dev_info(&nvavp->nvhost_dev->dev,
213 "AVP awaken event (0x%x)\n", inbox);
214 }
215 if (inbox & NVE276_OS_INTERRUPT_AVP_FATAL_ERROR) {
216 dev_err(&nvavp->nvhost_dev->dev,
217 "fatal AVP error (0x%08X)\n", inbox);
218 }
219 if (inbox & NVE276_OS_INTERRUPT_AVP_BREAKPOINT)
220 dev_err(&nvavp->nvhost_dev->dev, "AVP breakpoint hit\n");
221 if (inbox & NVE276_OS_INTERRUPT_TIMEOUT)
222 dev_err(&nvavp->nvhost_dev->dev, "AVP timeout\n");
223
224 return 0;
225}
226
227static irqreturn_t nvavp_mbox_pending_isr(int irq, void *data)
228{
229 struct nvavp_info *nvavp = data;
230
231 nvavp_service(nvavp);
232
233 return IRQ_HANDLED;
234}
235
236static void nvavp_halt_avp(struct nvavp_info *nvavp)
237{
238 /* ensure the AVP is halted */
239 writel(FLOW_MODE_STOP, FLOW_CTRL_HALT_COP_EVENTS);
240 tegra_periph_reset_assert(nvavp->cop_clk);
241
242 writel(0, NVAVP_OS_OUTBOX);
243 writel(0, NVAVP_OS_INBOX);
244}
245
246static int nvavp_reset_avp(struct nvavp_info *nvavp, unsigned long reset_addr)
247{
248#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU)
249 unsigned long stub_code_phys = virt_to_phys(_tegra_avp_boot_stub);
250 dma_addr_t stub_data_phys;
251
252 _tegra_avp_boot_stub_data.map_phys_addr = avp->kernel_phys;
253 _tegra_avp_boot_stub_data.jump_addr = reset_addr;
254 wmb();
255 stub_data_phys = dma_map_single(NULL, &_tegra_avp_boot_stub_data,
256 sizeof(_tegra_avp_boot_stub_data),
257 DMA_TO_DEVICE);
258 rmb();
259 reset_addr = (unsigned long)stub_data_phys;
260#endif
261 writel(FLOW_MODE_STOP, FLOW_CTRL_HALT_COP_EVENTS);
262
263 writel(reset_addr, TEGRA_NVAVP_RESET_VECTOR_ADDR);
264
265 clk_enable(nvavp->sclk);
266 clk_enable(nvavp->emc_clk);
267
268 /* If sclk_rate and emc_clk is not set by user space,
269 * max clock in dvfs table will be used to get best performance.
270 */
271 nvavp->sclk_rate = ULONG_MAX;
272 nvavp->emc_clk_rate = ULONG_MAX;
273
274 tegra_periph_reset_assert(nvavp->cop_clk);
275 udelay(2);
276 tegra_periph_reset_deassert(nvavp->cop_clk);
277
278 writel(FLOW_MODE_NONE, FLOW_CTRL_HALT_COP_EVENTS);
279
280#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU)
281 dma_unmap_single(NULL, stub_data_phys,
282 sizeof(_tegra_avp_boot_stub_data),
283 DMA_TO_DEVICE);
284#endif
285 return 0;
286}
287
288static void nvavp_halt_vde(struct nvavp_info *nvavp)
289{
290 if (nvavp->clk_enabled) {
291 tegra_periph_reset_assert(nvavp->bsev_clk);
292 clk_disable(nvavp->bsev_clk);
293 tegra_periph_reset_assert(nvavp->vde_clk);
294 clk_disable(nvavp->vde_clk);
295 nvhost_module_idle(nvhost_get_host(nvavp->nvhost_dev)->dev);
296 nvavp->clk_enabled = 0;
297 }
298}
299
300static int nvavp_reset_vde(struct nvavp_info *nvavp)
301{
302 if (!nvavp->clk_enabled)
303 nvhost_module_busy(nvhost_get_host(nvavp->nvhost_dev)->dev);
304
305 clk_enable(nvavp->bsev_clk);
306 tegra_periph_reset_assert(nvavp->bsev_clk);
307 udelay(2);
308 tegra_periph_reset_deassert(nvavp->bsev_clk);
309
310 clk_enable(nvavp->vde_clk);
311 tegra_periph_reset_assert(nvavp->vde_clk);
312 udelay(2);
313 tegra_periph_reset_deassert(nvavp->vde_clk);
314
315 /*
316 * VDE clock is set to max freq by default.
317 * VDE clock can be set to different freq if needed
318 * through ioctl.
319 */
320 clk_set_rate(nvavp->vde_clk, ULONG_MAX);
321
322 nvavp->clk_enabled = 1;
323 return 0;
324}
325
326static int nvavp_pushbuffer_alloc(struct nvavp_info *nvavp)
327{
328 int ret = 0;
329
330 nvavp->pushbuf_handle = nvmap_alloc(nvavp->nvmap, NVAVP_PUSHBUFFER_SIZE,
331 SZ_1M, NVMAP_HANDLE_UNCACHEABLE, 0);
332 if (IS_ERR(nvavp->pushbuf_handle)) {
333 dev_err(&nvavp->nvhost_dev->dev,
334 "cannot create pushbuffer handle\n");
335 ret = PTR_ERR(nvavp->pushbuf_handle);
336 goto err_pushbuf_alloc;
337 }
338 nvavp->pushbuf_data = (u8 *)nvmap_mmap(nvavp->pushbuf_handle);
339 if (!nvavp->pushbuf_data) {
340 dev_err(&nvavp->nvhost_dev->dev,
341 "cannot map pushbuffer handle\n");
342 ret = -ENOMEM;
343 goto err_pushbuf_mmap;
344 }
345 nvavp->pushbuf_phys = nvmap_pin(nvavp->nvmap, nvavp->pushbuf_handle);
346 if (IS_ERR((void *)nvavp->pushbuf_phys)) {
347 dev_err(&nvavp->nvhost_dev->dev,
348 "cannot pin pushbuffer handle\n");
349 ret = PTR_ERR((void *)nvavp->pushbuf_phys);
350 goto err_pushbuf_pin;
351 }
352
353 memset(nvavp->pushbuf_data, 0, NVAVP_PUSHBUFFER_SIZE);
354
355 return 0;
356
357err_pushbuf_pin:
358 nvmap_munmap(nvavp->pushbuf_handle, nvavp->pushbuf_data);
359err_pushbuf_mmap:
360 nvmap_free(nvavp->nvmap, nvavp->pushbuf_handle);
361err_pushbuf_alloc:
362 return ret;
363}
364
365static void nvavp_pushbuffer_free(struct nvavp_info *nvavp)
366{
367 nvmap_unpin(nvavp->nvmap, nvavp->pushbuf_handle);
368 nvmap_munmap(nvavp->pushbuf_handle, nvavp->pushbuf_data);
369 nvmap_free(nvavp->nvmap, nvavp->pushbuf_handle);
370}
371
372static int nvavp_pushbuffer_init(struct nvavp_info *nvavp)
373{
374 void *ptr;
375 struct nvavp_os_info *os = &nvavp->os_info;
376 struct nv_e276_control *control;
377 u32 temp;
378 int ret;
379
380 ret = nvavp_pushbuffer_alloc(nvavp);
381 if (ret) {
382 dev_err(&nvavp->nvhost_dev->dev,
383 "unable to alloc pushbuffer\n");
384 return ret;
385 }
386
387 ptr = os->data;
388 ptr += os->control_offset;
389 nvavp->os_control = (struct nv_e276_control *)ptr;
390
391 control = nvavp->os_control;
392 memset(control, 0, sizeof(struct nvavp_os_info));
393
394 /* init get and put pointers */
395 writel(0x0, &control->put);
396 writel(0x0, &control->get);
397
398 /* enable avp VDE clock control and disable iram clock gating */
399 writel(0x0, &control->idle_clk_enable);
400 writel(0x0, &control->iram_clk_gating);
401
402 /* enable avp idle timeout interrupt */
403 writel(0x1, &control->idle_notify_enable);
404 writel(NVAVP_OS_IDLE_TIMEOUT, &control->idle_notify_delay);
405
406 /* init dma start and end pointers */
407 writel(nvavp->pushbuf_phys, &control->dma_start);
408 writel((nvavp->pushbuf_phys + NVAVP_PUSHBUFFER_SIZE),
409 &control->dma_end);
410
411 writel(0x00, &nvavp->pushbuf_index);
412 temp = NVAVP_PUSHBUFFER_SIZE - NVAVP_PUSHBUFFER_MIN_UPDATE_SPACE;
413 writel(temp, &nvavp->pushbuf_fence);
414
415 nvavp->syncpt_id = NVSYNCPT_AVP_0;
416 nvavp->syncpt_value = nvhost_syncpt_read(nvavp->nvhost_syncpt,
417 nvavp->syncpt_id);
418
419 return 0;
420}
421
422static void nvavp_pushbuffer_deinit(struct nvavp_info *nvavp)
423{
424 nvavp_pushbuffer_free(nvavp);
425}
426
427static int nvavp_pushbuffer_update(struct nvavp_info *nvavp, u32 phys_addr,
428 u32 gather_count, struct nvavp_syncpt *syncpt,
429 u32 ext_ucode_flag)
430{
431 struct nv_e276_control *control = nvavp->os_control;
432 u32 gather_cmd, setucode_cmd, sync = 0;
433 u32 wordcount = 0;
434 u32 index, value = -1;
435
436 mutex_lock(&nvavp->pushbuffer_lock);
437
438 /* check for pushbuffer wrapping */
439 if (nvavp->pushbuf_index >= nvavp->pushbuf_fence)
440 nvavp->pushbuf_index = 0;
441
442 if (!ext_ucode_flag) {
443 setucode_cmd =
444 NVE26E_CH_OPCODE_INCR(NVE276_SET_MICROCODE_A, 3);
445
446 index = wordcount + nvavp->pushbuf_index;
447 writel(setucode_cmd, (nvavp->pushbuf_data + index));
448 wordcount += sizeof(u32);
449
450 index = wordcount + nvavp->pushbuf_index;
451 writel(0, (nvavp->pushbuf_data + index));
452 wordcount += sizeof(u32);
453
454 index = wordcount + nvavp->pushbuf_index;
455 writel(nvavp->ucode_info.phys, (nvavp->pushbuf_data + index));
456 wordcount += sizeof(u32);
457
458 index = wordcount + nvavp->pushbuf_index;
459 writel(nvavp->ucode_info.size, (nvavp->pushbuf_data + index));
460 wordcount += sizeof(u32);
461 }
462
463 gather_cmd = NVE26E_CH_OPCODE_GATHER(0, 0, 0, gather_count);
464
465 if (syncpt) {
466 value = ++nvavp->syncpt_value;
467 /* XXX: NvSchedValueWrappingComparison */
468 sync = NVE26E_CH_OPCODE_IMM(NVE26E_HOST1X_INCR_SYNCPT,
469 (NVE26E_HOST1X_INCR_SYNCPT_COND_OP_DONE << 8) |
470 (nvavp->syncpt_id & 0xFF));
471 }
472
473 /* write commands out */
474 index = wordcount + nvavp->pushbuf_index;
475 writel(gather_cmd, (nvavp->pushbuf_data + index));
476 wordcount += sizeof(u32);
477
478 index = wordcount + nvavp->pushbuf_index;
479 writel(phys_addr, (nvavp->pushbuf_data + index));
480 wordcount += sizeof(u32);
481
482 if (syncpt) {
483 index = wordcount + nvavp->pushbuf_index;
484 writel(sync, (nvavp->pushbuf_data + index));
485 wordcount += sizeof(u32);
486 }
487
488 /* enable clocks to VDE/BSEV */
489 nvavp_clk_ctrl(nvavp, 1);
490
491 /* update put pointer */
492 nvavp->pushbuf_index = (nvavp->pushbuf_index + wordcount) &
493 (NVAVP_PUSHBUFFER_SIZE - 1);
494 writel(nvavp->pushbuf_index, &control->put);
495 wmb();
496
497 /* wake up avp */
498 writel(0xA0000001, NVAVP_OS_OUTBOX);
499
500 /* Fill out fence struct */
501 if (syncpt) {
502 syncpt->id = nvavp->syncpt_id;
503 syncpt->value = value;
504 }
505
506 mutex_unlock(&nvavp->pushbuffer_lock);
507
508 return 0;
509}
510
511static void nvavp_unload_ucode(struct nvavp_info *nvavp)
512{
513 nvmap_unpin(nvavp->nvmap, nvavp->ucode_info.handle);
514 nvmap_munmap(nvavp->ucode_info.handle, nvavp->ucode_info.data);
515 nvmap_free(nvavp->nvmap, nvavp->ucode_info.handle);
516 kfree(nvavp->ucode_info.ucode_bin);
517}
518
519static int nvavp_load_ucode(struct nvavp_info *nvavp)
520{
521 struct nvavp_ucode_info *ucode_info = &nvavp->ucode_info;
522 const struct firmware *nvavp_ucode_fw;
523 char fw_ucode_file[32];
524 void *ptr;
525 int ret = 0;
526
527 if (!ucode_info->ucode_bin) {
528 sprintf(fw_ucode_file, "nvavp_vid_ucode.bin");
529
530 ret = request_firmware(&nvavp_ucode_fw, fw_ucode_file,
531 nvavp->misc_dev.this_device);
532 if (ret) {
533 /* Try alternative version */
534 sprintf(fw_ucode_file, "nvavp_vid_ucode_alt.bin");
535
536 ret = request_firmware(&nvavp_ucode_fw,
537 fw_ucode_file,
538 nvavp->misc_dev.this_device);
539
540 if (ret) {
541 dev_err(&nvavp->nvhost_dev->dev,
542 "cannot read ucode firmware '%s'\n",
543 fw_ucode_file);
544 goto err_req_ucode;
545 }
546 }
547
548 dev_info(&nvavp->nvhost_dev->dev,
549 "read ucode firmware from '%s' (%d bytes)\n",
550 fw_ucode_file, nvavp_ucode_fw->size);
551
552 ptr = (void *)nvavp_ucode_fw->data;
553
554 if (strncmp((const char *)ptr, "NVAVPAPP", 8)) {
555 dev_info(&nvavp->nvhost_dev->dev,
556 "ucode hdr string mismatch\n");
557 ret = -EINVAL;
558 goto err_req_ucode;
559 }
560 ptr += 8;
561 ucode_info->size = nvavp_ucode_fw->size - 8;
562
563 ucode_info->ucode_bin = kzalloc(ucode_info->size,
564 GFP_KERNEL);
565 if (!ucode_info->ucode_bin) {
566 dev_err(&nvavp->nvhost_dev->dev,
567 "cannot allocate ucode bin\n");
568 ret = -ENOMEM;
569 goto err_ubin_alloc;
570 }
571
572 ucode_info->handle = nvmap_alloc(nvavp->nvmap,
573 nvavp->ucode_info.size,
574 SZ_1M, NVMAP_HANDLE_UNCACHEABLE, 0);
575 if (IS_ERR(ucode_info->handle)) {
576 dev_err(&nvavp->nvhost_dev->dev,
577 "cannot create ucode handle\n");
578 ret = PTR_ERR(ucode_info->handle);
579 goto err_ucode_alloc;
580 }
581 ucode_info->data = (u8 *)nvmap_mmap(ucode_info->handle);
582 if (!ucode_info->data) {
583 dev_err(&nvavp->nvhost_dev->dev,
584 "cannot map ucode handle\n");
585 ret = -ENOMEM;
586 goto err_ucode_mmap;
587 }
588 ucode_info->phys = nvmap_pin(nvavp->nvmap, ucode_info->handle);
589 if (IS_ERR((void *)ucode_info->phys)) {
590 dev_err(&nvavp->nvhost_dev->dev,
591 "cannot pin ucode handle\n");
592 ret = PTR_ERR((void *)ucode_info->phys);
593 goto err_ucode_pin;
594 }
595 memcpy(ucode_info->ucode_bin, ptr, ucode_info->size);
596 release_firmware(nvavp_ucode_fw);
597 }
598
599 memcpy(ucode_info->data, ucode_info->ucode_bin, ucode_info->size);
600 return 0;
601
602err_ucode_pin:
603 nvmap_munmap(ucode_info->handle, ucode_info->data);
604err_ucode_mmap:
605 nvmap_free(nvavp->nvmap, ucode_info->handle);
606err_ucode_alloc:
607 kfree(nvavp->ucode_info.ucode_bin);
608err_ubin_alloc:
609 release_firmware(nvavp_ucode_fw);
610err_req_ucode:
611 return ret;
612}
613
614static void nvavp_unload_os(struct nvavp_info *nvavp)
615{
616 nvmap_unpin(nvavp->nvmap, nvavp->os_info.handle);
617 nvmap_munmap(nvavp->os_info.handle, nvavp->os_info.data);
618#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU)
619 nvmap_free(nvavp->nvmap, nvavp->os_info.handle);
620#elif defined(CONFIG_TEGRA_AVP_KERNEL_ON_SMMU)
621 nvmap_free_iovm(nvavp->nvmap, nvavp->os_info.handle);
622#endif
623 kfree(nvavp->os_info.os_bin);
624}
625
626static int nvavp_load_os(struct nvavp_info *nvavp, char *fw_os_file)
627{
628 struct nvavp_os_info *os_info = &nvavp->os_info;
629 const struct firmware *nvavp_os_fw;
630 void *ptr;
631 u32 size;
632 int ret = 0;
633
634 if (!os_info->os_bin) {
635 ret = request_firmware(&nvavp_os_fw, fw_os_file,
636 nvavp->misc_dev.this_device);
637 if (ret) {
638 dev_err(&nvavp->nvhost_dev->dev,
639 "cannot read os firmware '%s'\n", fw_os_file);
640 goto err_req_fw;
641 }
642
643 dev_info(&nvavp->nvhost_dev->dev,
644 "read firmware from '%s' (%d bytes)\n",
645 fw_os_file, nvavp_os_fw->size);
646
647 ptr = (void *)nvavp_os_fw->data;
648
649 if (strncmp((const char *)ptr, "NVAVP-OS", 8)) {
650 dev_info(&nvavp->nvhost_dev->dev,
651 "os hdr string mismatch\n");
652 ret = -EINVAL;
653 goto err_os_bin;
654 }
655
656 ptr += 8;
657 os_info->entry_offset = *((u32 *)ptr);
658 ptr += sizeof(u32);
659 os_info->control_offset = *((u32 *)ptr);
660 ptr += sizeof(u32);
661 os_info->debug_offset = *((u32 *)ptr);
662 ptr += sizeof(u32);
663
664 size = *((u32 *)ptr); ptr += sizeof(u32);
665
666 os_info->size = size;
667 os_info->os_bin = kzalloc(os_info->size,
668 GFP_KERNEL);
669 if (!os_info->os_bin) {
670 dev_err(&nvavp->nvhost_dev->dev,
671 "cannot allocate os bin\n");
672 ret = -ENOMEM;
673 goto err_os_bin;
674 }
675
676 memcpy(os_info->os_bin, ptr, os_info->size);
677 memset(os_info->data + os_info->size, 0, SZ_1M - os_info->size);
678
679 dev_info(&nvavp->nvhost_dev->dev,
680 "entry=%08x control=%08x debug=%08x size=%d\n",
681 os_info->entry_offset, os_info->control_offset,
682 os_info->debug_offset, os_info->size);
683 release_firmware(nvavp_os_fw);
684 }
685
686 memcpy(os_info->data, os_info->os_bin, os_info->size);
687 os_info->reset_addr = os_info->phys + os_info->entry_offset;
688
689 dev_info(&nvavp->nvhost_dev->dev,
690 "AVP os at vaddr=%p paddr=%lx reset_addr=%p\n",
691 os_info->data, (unsigned long)(os_info->phys),
692 (void *)os_info->reset_addr);
693 return 0;
694
695err_os_bin:
696 release_firmware(nvavp_os_fw);
697err_req_fw:
698 return ret;
699}
700
701static int nvavp_init(struct nvavp_info *nvavp)
702{
703 char fw_os_file[32];
704 int ret = 0;
705
706 if (nvavp->initialized)
707 return ret;
708
709#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU) /* Tegra2 with AVP MMU */
710 /* paddr is any address returned from nvmap_pin */
711 /* vaddr is AVP_KERNEL_VIRT_BASE */
712 dev_info(&nvavp->nvhost_dev->dev,
713 "using AVP MMU to relocate AVP os\n");
714 sprintf(fw_os_file, "nvavp_os.bin");
715 nvavp->os_info.reset_addr = AVP_KERNEL_VIRT_BASE;
716#elif defined(CONFIG_TEGRA_AVP_KERNEL_ON_SMMU) /* Tegra3 with SMMU */
717 /* paddr is any address behind SMMU */
718 /* vaddr is TEGRA_SMMU_BASE */
719 dev_info(&nvavp->nvhost_dev->dev,
720 "using SMMU at %lx to load AVP kernel\n",
721 (unsigned long)nvavp->os_info.phys);
722 BUG_ON(nvavp->os_info.phys != 0xeff00000
723 && nvavp->os_info.phys != 0x0ff00000);
724 sprintf(fw_os_file, "nvavp_os_%08lx.bin",
725 (unsigned long)nvavp->os_info.phys);
726 nvavp->os_info.reset_addr = nvavp->os_info.phys;
727#else /* nvmem= carveout */
728 /* paddr is found in nvmem= carveout */
729 /* vaddr is same as paddr */
730 /* Find nvmem carveout */
731 if (!pfn_valid(__phys_to_pfn(0x8e000000))) {
732 nvavp->os_info.phys = 0x8e000000;
733 } else if (!pfn_valid(__phys_to_pfn(0x9e000000))) {
734 nvavp->os_info.phys = 0x9e000000;
735 } else if (!pfn_valid(__phys_to_pfn(0xbe000000))) {
736 nvavp->os_info.phys = 0xbe000000;
737 } else {
738 dev_err(&nvavp->nvhost_dev->dev,
739 "cannot find nvmem= carveout to load AVP os\n");
740 dev_err(&nvavp->nvhost_dev->dev,
741 "check kernel command line "
742 "to see if nvmem= is defined\n");
743 BUG();
744 }
745 dev_info(&nvavp->nvhost_dev->dev,
746 "using nvmem= carveout at %lx to load AVP os\n",
747 nvavp->os_info.phys);
748 sprintf(fw_os_file, "nvavp_os_%08lx.bin", nvavp->os_info.phys);
749 nvavp->os_info.reset_addr = nvavp->os_info.phys;
750 nvavp->os_info.data = ioremap(nvavp->os_info.phys, SZ_1M);
751#endif
752
753 ret = nvavp_load_os(nvavp, fw_os_file);
754 if (ret) {
755 dev_err(&nvavp->nvhost_dev->dev,
756 "unable to load os firmware '%s'\n", fw_os_file);
757 goto err_exit;
758 }
759
760 ret = nvavp_pushbuffer_init(nvavp);
761 if (ret) {
762 dev_err(&nvavp->nvhost_dev->dev,
763 "unable to init pushbuffer\n");
764 goto err_exit;
765 }
766
767 ret = nvavp_load_ucode(nvavp);
768 if (ret) {
769 dev_err(&nvavp->nvhost_dev->dev,
770 "unable to load ucode\n");
771 goto err_exit;
772 }
773
774 tegra_init_legacy_irq_cop();
775
776 nvavp_reset_vde(nvavp);
777 nvavp_reset_avp(nvavp, nvavp->os_info.reset_addr);
778 enable_irq(nvavp->mbox_from_avp_pend_irq);
779
780 nvavp->initialized = 1;
781
782err_exit:
783 return ret;
784}
785
786static void nvavp_uninit(struct nvavp_info *nvavp)
787{
788 if (!nvavp->initialized)
789 return;
790
791 disable_irq(nvavp->mbox_from_avp_pend_irq);
792
793 cancel_work_sync(&nvavp->clock_disable_work);
794
795 nvavp_pushbuffer_deinit(nvavp);
796
797 nvavp_halt_vde(nvavp);
798 nvavp_halt_avp(nvavp);
799
800 clk_disable(nvavp->sclk);
801 clk_disable(nvavp->emc_clk);
802
803 nvavp->initialized = 0;
804}
805
806static int nvavp_set_clock_ioctl(struct file *filp, unsigned int cmd,
807 unsigned long arg)
808{
809 struct nvavp_clientctx *clientctx = filp->private_data;
810 struct nvavp_info *nvavp = clientctx->nvavp;
811 struct clk *c;
812 struct nvavp_clock_args config;
813
814 if (copy_from_user(&config, (void __user *)arg, sizeof(struct nvavp_clock_args)))
815 return -EFAULT;
816
817 dev_dbg(&nvavp->nvhost_dev->dev, "%s: clk_id=%d, clk_rate=%u\n",
818 __func__, config.id, config.rate);
819
820 if (config.id == NVAVP_MODULE_ID_AVP)
821 nvavp->sclk_rate = config.rate;
822 else if (config.id == NVAVP_MODULE_ID_EMC)
823 nvavp->emc_clk_rate = config.rate;
824
825 c = nvavp_clk_get(nvavp, config.id);
826 if (IS_ERR_OR_NULL(c))
827 return -EINVAL;
828
829 clk_enable(c);
830 clk_set_rate(c, config.rate);
831
832 config.rate = clk_get_rate(c);
833 clk_disable(c);
834 if (copy_to_user((void __user *)arg, &config, sizeof(struct nvavp_clock_args)))
835 return -EFAULT;
836
837 return 0;
838}
839
840static int nvavp_get_clock_ioctl(struct file *filp, unsigned int cmd,
841 unsigned long arg)
842{
843 struct nvavp_clientctx *clientctx = filp->private_data;
844 struct nvavp_info *nvavp = clientctx->nvavp;
845 struct clk *c;
846 struct nvavp_clock_args config;
847
848 if (copy_from_user(&config, (void __user *)arg, sizeof(struct nvavp_clock_args)))
849 return -EFAULT;
850
851 c = nvavp_clk_get(nvavp, config.id);
852 if (IS_ERR_OR_NULL(c))
853 return -EINVAL;
854
855 clk_enable(c);
856 config.rate = clk_get_rate(c);
857 clk_disable(c);
858
859 if (copy_to_user((void __user *)arg, &config, sizeof(struct nvavp_clock_args)))
860 return -EFAULT;
861
862 return 0;
863}
864
865static int nvavp_get_syncpointid_ioctl(struct file *filp, unsigned int cmd,
866 unsigned long arg)
867{
868 struct nvavp_clientctx *clientctx = filp->private_data;
869 struct nvavp_info *nvavp = clientctx->nvavp;
870 u32 id = nvavp->syncpt_id;
871
872 if (_IOC_DIR(cmd) & _IOC_READ) {
873 if (copy_to_user((void __user *)arg, &id, sizeof(u32)))
874 return -EFAULT;
875 else
876 return 0;
877 }
878 return -EFAULT;
879}
880
881static int nvavp_set_nvmapfd_ioctl(struct file *filp, unsigned int cmd,
882 unsigned long arg)
883{
884 struct nvavp_clientctx *clientctx = filp->private_data;
885 struct nvavp_set_nvmap_fd_args buf;
886 struct nvmap_client *new_client;
887 int fd;
888
889 if (_IOC_DIR(cmd) & _IOC_WRITE) {
890 if (copy_from_user(&buf, (void __user *)arg, _IOC_SIZE(cmd)))
891 return -EFAULT;
892 }
893
894 fd = buf.fd;
895 new_client = nvmap_client_get_file(fd);
896 if (IS_ERR(new_client))
897 return PTR_ERR(new_client);
898
899 clientctx->nvmap = new_client;
900 return 0;
901}
902
903static int nvavp_pushbuffer_submit_ioctl(struct file *filp, unsigned int cmd,
904 unsigned long arg)
905{
906 struct nvavp_clientctx *clientctx = filp->private_data;
907 struct nvavp_info *nvavp = clientctx->nvavp;
908 struct nvavp_pushbuffer_submit_hdr hdr;
909 u32 *cmdbuf_data;
910 struct nvmap_handle *cmdbuf_handle = NULL;
911 struct nvmap_handle_ref *cmdbuf_dupe;
912 int ret = 0, i;
913 unsigned long phys_addr;
914 unsigned long virt_addr;
915 struct nvavp_pushbuffer_submit_hdr *user_hdr =
916 (struct nvavp_pushbuffer_submit_hdr *) arg;
917 struct nvavp_syncpt syncpt;
918
919 syncpt.id = NVSYNCPT_INVALID;
920 syncpt.value = 0;
921
922 if (_IOC_DIR(cmd) & _IOC_WRITE) {
923 if (copy_from_user(&hdr, (void __user *)arg,
924 sizeof(struct nvavp_pushbuffer_submit_hdr)))
925 return -EFAULT;
926 }
927
928 if (!hdr.cmdbuf.mem)
929 return 0;
930
931 if (copy_from_user(clientctx->relocs, (void __user *)hdr.relocs,
932 sizeof(struct nvavp_reloc) * hdr.num_relocs)) {
933 return -EFAULT;
934 }
935
936 cmdbuf_handle = nvmap_get_handle_id(clientctx->nvmap, hdr.cmdbuf.mem);
937 if (cmdbuf_handle == NULL) {
938 dev_err(&nvavp->nvhost_dev->dev,
939 "invalid cmd buffer handle %08x\n", hdr.cmdbuf.mem);
940 return -EPERM;
941 }
942
943 /* duplicate the new pushbuffer's handle into the nvavp driver's
944 * nvmap context, to ensure that the handle won't be freed as
945 * long as it is in-use by the fb driver */
946 cmdbuf_dupe = nvmap_duplicate_handle_id(nvavp->nvmap, hdr.cmdbuf.mem);
947 nvmap_handle_put(cmdbuf_handle);
948
949 if (IS_ERR(cmdbuf_dupe)) {
950 dev_err(&nvavp->nvhost_dev->dev,
951 "could not duplicate handle\n");
952 return PTR_ERR(cmdbuf_dupe);
953 }
954
955 phys_addr = nvmap_pin(nvavp->nvmap, cmdbuf_dupe);
956 if (IS_ERR((void *)phys_addr)) {
957 dev_err(&nvavp->nvhost_dev->dev, "could not pin handle\n");
958 nvmap_free(nvavp->nvmap, cmdbuf_dupe);
959 return PTR_ERR((void *)phys_addr);
960 }
961
962 virt_addr = (unsigned long)nvmap_mmap(cmdbuf_dupe);
963 if (!virt_addr) {
964 dev_err(&nvavp->nvhost_dev->dev, "cannot map cmdbuf handle\n");
965 ret = -ENOMEM;
966 goto err_cmdbuf_mmap;
967 }
968
969 cmdbuf_data = (u32 *)(virt_addr + hdr.cmdbuf.offset);
970
971 for (i = 0; i < hdr.num_relocs; i++) {
972 u32 *reloc_addr, target_phys_addr;
973
974 if (clientctx->relocs[i].cmdbuf_mem != hdr.cmdbuf.mem) {
975 dev_err(&nvavp->nvhost_dev->dev,
976 "reloc info does not match target bufferID\n");
977 ret = -EPERM;
978 goto err_reloc_info;
979 }
980
981 reloc_addr = cmdbuf_data +
982 (clientctx->relocs[i].cmdbuf_offset >> 2);
983
984 target_phys_addr = nvmap_handle_address(clientctx->nvmap,
985 clientctx->relocs[i].target);
986 target_phys_addr += clientctx->relocs[i].target_offset;
987 writel(target_phys_addr, reloc_addr);
988 }
989
990 if (hdr.syncpt) {
991 ret = nvavp_pushbuffer_update(nvavp,
992 (phys_addr + hdr.cmdbuf.offset),
993 hdr.cmdbuf.words, &syncpt,
994 (hdr.flags & NVAVP_UCODE_EXT));
995
996 if (copy_to_user((void __user *)user_hdr->syncpt, &syncpt,
997 sizeof(struct nvavp_syncpt))) {
998 ret = -EFAULT;
999 goto err_reloc_info;
1000 }
1001 } else {
1002 ret = nvavp_pushbuffer_update(nvavp,
1003 (phys_addr + hdr.cmdbuf.offset),
1004 hdr.cmdbuf.words, NULL,
1005 (hdr.flags & NVAVP_UCODE_EXT));
1006 }
1007
1008err_reloc_info:
1009 nvmap_munmap(cmdbuf_dupe, (void *)virt_addr);
1010err_cmdbuf_mmap:
1011 nvmap_unpin(nvavp->nvmap, cmdbuf_dupe);
1012 nvmap_free(nvavp->nvmap, cmdbuf_dupe);
1013 return ret;
1014}
1015
1016static int tegra_nvavp_open(struct inode *inode, struct file *filp)
1017{
1018 struct miscdevice *miscdev = filp->private_data;
1019 struct nvavp_info *nvavp = dev_get_drvdata(miscdev->parent);
1020 int ret = 0;
1021 struct nvavp_clientctx *clientctx;
1022
1023 dev_dbg(&nvavp->nvhost_dev->dev, "%s: ++\n", __func__);
1024
1025 nonseekable_open(inode, filp);
1026
1027 clientctx = kzalloc(sizeof(*clientctx), GFP_KERNEL);
1028 if (!clientctx)
1029 return -ENOMEM;
1030
1031 mutex_lock(&nvavp->open_lock);
1032
1033 if (!nvavp->refcount)
1034 ret = nvavp_init(nvavp);
1035
1036 if (!ret)
1037 nvavp->refcount++;
1038
1039 clientctx->nvmap = nvavp->nvmap;
1040 clientctx->nvavp = nvavp;
1041
1042 filp->private_data = clientctx;
1043
1044 mutex_unlock(&nvavp->open_lock);
1045
1046 return ret;
1047}
1048
1049static int tegra_nvavp_release(struct inode *inode, struct file *filp)
1050{
1051 struct nvavp_clientctx *clientctx = filp->private_data;
1052 struct nvavp_info *nvavp = clientctx->nvavp;
1053 int ret = 0;
1054
1055 dev_dbg(&nvavp->nvhost_dev->dev, "%s: ++\n", __func__);
1056
1057 filp->private_data = NULL;
1058
1059 mutex_lock(&nvavp->open_lock);
1060
1061 if (!nvavp->refcount) {
1062 dev_err(&nvavp->nvhost_dev->dev,
1063 "releasing while in invalid state\n");
1064 ret = -EINVAL;
1065 goto out;
1066 }
1067
1068 if (nvavp->refcount > 0)
1069 nvavp->refcount--;
1070 if (!nvavp->refcount)
1071 nvavp_uninit(nvavp);
1072
1073out:
1074 nvmap_client_put(clientctx->nvmap);
1075 mutex_unlock(&nvavp->open_lock);
1076 kfree(clientctx);
1077 return ret;
1078}
1079
1080static long tegra_nvavp_ioctl(struct file *filp, unsigned int cmd,
1081 unsigned long arg)
1082{
1083 int ret = 0;
1084
1085 if (_IOC_TYPE(cmd) != NVAVP_IOCTL_MAGIC ||
1086 _IOC_NR(cmd) < NVAVP_IOCTL_MIN_NR ||
1087 _IOC_NR(cmd) > NVAVP_IOCTL_MAX_NR)
1088 return -EFAULT;
1089
1090 switch (cmd) {
1091 case NVAVP_IOCTL_SET_NVMAP_FD:
1092 ret = nvavp_set_nvmapfd_ioctl(filp, cmd, arg);
1093 break;
1094 case NVAVP_IOCTL_GET_SYNCPOINT_ID:
1095 ret = nvavp_get_syncpointid_ioctl(filp, cmd, arg);
1096 break;
1097 case NVAVP_IOCTL_PUSH_BUFFER_SUBMIT:
1098 ret = nvavp_pushbuffer_submit_ioctl(filp, cmd, arg);
1099 break;
1100 case NVAVP_IOCTL_SET_CLOCK:
1101 ret = nvavp_set_clock_ioctl(filp, cmd, arg);
1102 break;
1103 case NVAVP_IOCTL_GET_CLOCK:
1104 ret = nvavp_get_clock_ioctl(filp, cmd, arg);
1105 break;
1106 default:
1107 ret = -EINVAL;
1108 break;
1109 }
1110 return ret;
1111}
1112
1113static const struct file_operations tegra_nvavp_fops = {
1114 .owner = THIS_MODULE,
1115 .open = tegra_nvavp_open,
1116 .release = tegra_nvavp_release,
1117 .unlocked_ioctl = tegra_nvavp_ioctl,
1118};
1119
1120static int tegra_nvavp_probe(struct nvhost_device *ndev)
1121{
1122 struct nvavp_info *nvavp;
1123 int irq;
1124 unsigned int heap_mask;
1125 u32 iovmm_addr;
1126 int ret = 0;
1127
1128 irq = nvhost_get_irq_byname(ndev, "mbox_from_nvavp_pending");
1129 if (irq < 0) {
1130 dev_err(&ndev->dev, "invalid nvhost data\n");
1131 return -EINVAL;
1132 }
1133
1134
1135 nvavp = kzalloc(sizeof(struct nvavp_info), GFP_KERNEL);
1136 if (!nvavp) {
1137 dev_err(&ndev->dev, "cannot allocate avp_info\n");
1138 return -ENOMEM;
1139 }
1140
1141 memset(nvavp, 0, sizeof(*nvavp));
1142
1143 nvavp->nvhost_syncpt = &nvhost_get_host(ndev)->syncpt;
1144 if (!nvavp->nvhost_syncpt) {
1145 dev_err(&ndev->dev, "cannot get syncpt handle\n");
1146 ret = -ENOENT;
1147 goto err_get_syncpt;
1148 }
1149
1150 nvavp->nvmap = nvmap_create_client(nvmap_dev, "nvavp_drv");
1151 if (IS_ERR_OR_NULL(nvavp->nvmap)) {
1152 dev_err(&ndev->dev, "cannot create nvmap client\n");
1153 ret = PTR_ERR(nvavp->nvmap);
1154 goto err_nvmap_create_drv_client;
1155 }
1156
1157#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU) /* Tegra2 with AVP MMU */
1158 heap_mask = NVMAP_HEAP_CARVEOUT_GENERIC;
1159#elif defined(CONFIG_TEGRA_AVP_KERNEL_ON_SMMU) /* Tegra3 with SMMU */
1160 heap_mask = NVMAP_HEAP_IOVMM;
1161#else /* nvmem= carveout */
1162 heap_mask = 0;
1163#endif
1164 switch (heap_mask) {
1165 case NVMAP_HEAP_IOVMM:
1166
1167#ifdef CONFIG_TEGRA_SMMU_BASE_AT_E0000000
1168 iovmm_addr = 0xeff00000;
1169#else
1170 iovmm_addr = 0x0ff00000;
1171#endif
1172
1173 /* Tegra3 A01 has different SMMU address */
1174 if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3
1175 && tegra_get_revision() == TEGRA_REVISION_A01) {
1176 iovmm_addr = 0xeff00000;
1177 }
1178
1179 nvavp->os_info.handle = nvmap_alloc_iovm(nvavp->nvmap, SZ_1M,
1180 L1_CACHE_BYTES,
1181 NVMAP_HANDLE_UNCACHEABLE,
1182 iovmm_addr);
1183 if (IS_ERR_OR_NULL(nvavp->os_info.handle)) {
1184 dev_err(&ndev->dev,
1185 "cannot create os handle\n");
1186 ret = PTR_ERR(nvavp->os_info.handle);
1187 goto err_nvmap_alloc;
1188 }
1189
1190 nvavp->os_info.data = nvmap_mmap(nvavp->os_info.handle);
1191 if (!nvavp->os_info.data) {
1192 dev_err(&ndev->dev,
1193 "cannot map os handle\n");
1194 ret = -ENOMEM;
1195 goto err_nvmap_mmap;
1196 }
1197
1198 nvavp->os_info.phys =
1199 nvmap_pin(nvavp->nvmap, nvavp->os_info.handle);
1200 if (IS_ERR_OR_NULL((void *)nvavp->os_info.phys)) {
1201 dev_err(&ndev->dev,
1202 "cannot pin os handle\n");
1203 ret = PTR_ERR((void *)nvavp->os_info.phys);
1204 goto err_nvmap_pin;
1205 }
1206
1207 dev_info(&ndev->dev,
1208 "allocated IOVM at %lx for AVP os\n",
1209 (unsigned long)nvavp->os_info.phys);
1210 break;
1211 case NVMAP_HEAP_CARVEOUT_GENERIC:
1212 nvavp->os_info.handle = nvmap_alloc(nvavp->nvmap, SZ_1M, SZ_1M,
1213 NVMAP_HANDLE_UNCACHEABLE, 0);
1214 if (IS_ERR_OR_NULL(nvavp->os_info.handle)) {
1215 dev_err(&ndev->dev, "cannot create AVP os handle\n");
1216 ret = PTR_ERR(nvavp->os_info.handle);
1217 goto err_nvmap_alloc;
1218 }
1219
1220 nvavp->os_info.data = nvmap_mmap(nvavp->os_info.handle);
1221 if (!nvavp->os_info.data) {
1222 dev_err(&ndev->dev, "cannot map AVP os handle\n");
1223 ret = -ENOMEM;
1224 goto err_nvmap_mmap;
1225 }
1226
1227 nvavp->os_info.phys = nvmap_pin(nvavp->nvmap,
1228 nvavp->os_info.handle);
1229 if (IS_ERR_OR_NULL((void *)nvavp->os_info.phys)) {
1230 dev_err(&ndev->dev, "cannot pin AVP os handle\n");
1231 ret = PTR_ERR((void *)nvavp->os_info.phys);
1232 goto err_nvmap_pin;
1233 }
1234
1235 dev_info(&ndev->dev,
1236 "allocated carveout memory at %lx for AVP os\n",
1237 (unsigned long)nvavp->os_info.phys);
1238 break;
1239 default:
1240 dev_err(&ndev->dev, "invalid/non-supported heap for AVP os\n");
1241 ret = -EINVAL;
1242 goto err_get_syncpt;
1243 }
1244
1245 nvavp->mbox_from_avp_pend_irq = irq;
1246 mutex_init(&nvavp->open_lock);
1247 mutex_init(&nvavp->pushbuffer_lock);
1248
1249 /* TODO DO NOT USE NVAVP DEVICE */
1250 nvavp->cop_clk = clk_get(&ndev->dev, "cop");
1251 if (IS_ERR(nvavp->cop_clk)) {
1252 dev_err(&ndev->dev, "cannot get cop clock\n");
1253 ret = -ENOENT;
1254 goto err_get_cop_clk;
1255 }
1256
1257 nvavp->vde_clk = clk_get(&ndev->dev, "vde");
1258 if (IS_ERR(nvavp->vde_clk)) {
1259 dev_err(&ndev->dev, "cannot get vde clock\n");
1260 ret = -ENOENT;
1261 goto err_get_vde_clk;
1262 }
1263
1264 nvavp->bsev_clk = clk_get(&ndev->dev, "bsev");
1265 if (IS_ERR(nvavp->bsev_clk)) {
1266 dev_err(&ndev->dev, "cannot get bsev clock\n");
1267 ret = -ENOENT;
1268 goto err_get_bsev_clk;
1269 }
1270
1271 nvavp->sclk = clk_get(&ndev->dev, "sclk");
1272 if (IS_ERR(nvavp->sclk)) {
1273 dev_err(&ndev->dev, "cannot get avp.sclk clock\n");
1274 ret = -ENOENT;
1275 goto err_get_sclk;
1276 }
1277
1278 nvavp->emc_clk = clk_get(&ndev->dev, "emc");
1279 if (IS_ERR(nvavp->emc_clk)) {
1280 dev_err(&ndev->dev, "cannot get emc clock\n");
1281 ret = -ENOENT;
1282 goto err_get_emc_clk;
1283 }
1284
1285 nvavp->clk_enabled = 0;
1286 nvavp_halt_avp(nvavp);
1287
1288 INIT_WORK(&nvavp->clock_disable_work, clock_disable_handler);
1289
1290 nvavp->misc_dev.minor = MISC_DYNAMIC_MINOR;
1291 nvavp->misc_dev.name = "tegra_avpchannel";
1292 nvavp->misc_dev.fops = &tegra_nvavp_fops;
1293 nvavp->misc_dev.mode = S_IRWXUGO;
1294 nvavp->misc_dev.parent = &ndev->dev;
1295
1296 ret = misc_register(&nvavp->misc_dev);
1297 if (ret) {
1298 dev_err(&ndev->dev, "unable to register misc device!\n");
1299 goto err_misc_reg;
1300 }
1301
1302 ret = request_irq(irq, nvavp_mbox_pending_isr, 0,
1303 TEGRA_NVAVP_NAME, nvavp);
1304 if (ret) {
1305 dev_err(&ndev->dev, "cannot register irq handler\n");
1306 goto err_req_irq_pend;
1307 }
1308 disable_irq(nvavp->mbox_from_avp_pend_irq);
1309
1310 nvhost_set_drvdata(ndev, nvavp);
1311 nvavp->nvhost_dev = ndev;
1312
1313 return 0;
1314
1315err_req_irq_pend:
1316 misc_deregister(&nvavp->misc_dev);
1317err_misc_reg:
1318 clk_put(nvavp->emc_clk);
1319err_get_emc_clk:
1320 clk_put(nvavp->sclk);
1321err_get_sclk:
1322 clk_put(nvavp->bsev_clk);
1323err_get_bsev_clk:
1324 clk_put(nvavp->vde_clk);
1325err_get_vde_clk:
1326 clk_put(nvavp->cop_clk);
1327err_get_cop_clk:
1328 nvmap_unpin(nvavp->nvmap, nvavp->os_info.handle);
1329err_nvmap_pin:
1330 nvmap_munmap(nvavp->os_info.handle, nvavp->os_info.data);
1331err_nvmap_mmap:
1332#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU)
1333 nvmap_free(nvavp->nvmap, nvavp->os_info.handle);
1334#elif defined(CONFIG_TEGRA_AVP_KERNEL_ON_SMMU)
1335 nvmap_free_iovm(nvavp->nvmap, nvavp->os_info.handle);
1336#endif
1337err_nvmap_alloc:
1338 nvmap_client_put(nvavp->nvmap);
1339err_nvmap_create_drv_client:
1340err_get_syncpt:
1341 kfree(nvavp);
1342 return ret;
1343}
1344
1345static int tegra_nvavp_remove(struct nvhost_device *ndev)
1346{
1347 struct nvavp_info *nvavp = nvhost_get_drvdata(ndev);
1348
1349 if (!nvavp)
1350 return 0;
1351
1352 mutex_lock(&nvavp->open_lock);
1353 if (nvavp->refcount) {
1354 mutex_unlock(&nvavp->open_lock);
1355 return -EBUSY;
1356 }
1357 mutex_unlock(&nvavp->open_lock);
1358
1359 nvavp_unload_ucode(nvavp);
1360 nvavp_unload_os(nvavp);
1361
1362 misc_deregister(&nvavp->misc_dev);
1363
1364 clk_put(nvavp->bsev_clk);
1365 clk_put(nvavp->vde_clk);
1366 clk_put(nvavp->cop_clk);
1367
1368 clk_put(nvavp->emc_clk);
1369 clk_put(nvavp->sclk);
1370
1371 nvmap_client_put(nvavp->nvmap);
1372
1373 kfree(nvavp);
1374 return 0;
1375}
1376
1377#ifdef CONFIG_PM
1378static int tegra_nvavp_suspend(struct nvhost_device *ndev, pm_message_t state)
1379{
1380 struct nvavp_info *nvavp = nvhost_get_drvdata(ndev);
1381 int ret = 0;
1382
1383 mutex_lock(&nvavp->open_lock);
1384
1385 if (nvavp->refcount) {
1386 if (nvavp_check_idle(nvavp))
1387 nvavp_uninit(nvavp);
1388 else
1389 ret = -EBUSY;
1390 }
1391
1392 mutex_unlock(&nvavp->open_lock);
1393
1394 return ret;
1395}
1396
1397static int tegra_nvavp_resume(struct nvhost_device *ndev)
1398{
1399 struct nvavp_info *nvavp = nvhost_get_drvdata(ndev);
1400
1401 mutex_lock(&nvavp->open_lock);
1402
1403 if (nvavp->refcount)
1404 nvavp_init(nvavp);
1405
1406 mutex_unlock(&nvavp->open_lock);
1407
1408 return 0;
1409}
1410#endif
1411
1412static struct nvhost_driver tegra_nvavp_driver = {
1413 .driver = {
1414 .name = TEGRA_NVAVP_NAME,
1415 .owner = THIS_MODULE,
1416 },
1417 .probe = tegra_nvavp_probe,
1418 .remove = tegra_nvavp_remove,
1419#ifdef CONFIG_PM
1420 .suspend = tegra_nvavp_suspend,
1421 .resume = tegra_nvavp_resume,
1422#endif
1423};
1424
1425static int __init tegra_nvavp_init(void)
1426{
1427 return nvhost_driver_register(&tegra_nvavp_driver);
1428}
1429
1430static void __exit tegra_nvavp_exit(void)
1431{
1432 nvhost_driver_unregister(&tegra_nvavp_driver);
1433}
1434
1435module_init(tegra_nvavp_init);
1436module_exit(tegra_nvavp_exit);
1437
1438MODULE_AUTHOR("NVIDIA");
1439MODULE_DESCRIPTION("Channel based AVP driver for Tegra");
1440MODULE_VERSION("1.0");
1441MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/media/video/tegra/nvavp/nvavp_os.h b/drivers/media/video/tegra/nvavp/nvavp_os.h
new file mode 100644
index 00000000000..4d7f6776f11
--- /dev/null
+++ b/drivers/media/video/tegra/nvavp/nvavp_os.h
@@ -0,0 +1,103 @@
1/*
2 * drivers/media/video/tegra/nvavp/nvavp_os.h
3 *
4 * Copyright (C) 2011 NVIDIA Corp.
5 *
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
9 */
10
11#ifndef __MEDIA_VIDEO_TEGRA_NVAVP_OS_H
12#define __MEDIA_VIDEO_TEGRA_NVAVP_OS_H
13
14#include <linux/types.h>
15
16#include "../../../../video/tegra/nvmap/nvmap.h"
17
18#define NVE2_AVP (0x0000E276)
19
20struct nv_e276_control {
21 u32 reserved00[5];
22 u32 dma_start;
23 u32 reserved01[2];
24 u32 dma_end;
25 u32 reserved02[7];
26 u32 put;
27 u32 reserved03[15];
28 u32 get;
29 u32 reserved04[10];
30 u32 watchdog_timeout;
31 u32 idle_notify_enable;
32 u32 idle_notify_delay;
33 u32 idle_clk_enable;
34 u32 iram_clk_gating;
35 u32 idle;
36 u32 outbox_data;
37 u32 app_intr_enable;
38 u32 app_start_time;
39 u32 app_in_iram;
40 u32 iram_ucode_addr;
41 u32 iram_ucode_size;
42 u32 dbg_state[57];
43 u32 os_method_data[16];
44 u32 app_method_data[128];
45};
46
47#define NVE26E_HOST1X_INCR_SYNCPT (0x00000000)
48#define NVE26E_HOST1X_INCR_SYNCPT_COND_OP_DONE (0x00000001)
49
50#define NVE26E_CH_OPCODE_INCR(Addr, Count) \
51 /* op, addr, count */ \
52 ((1UL << 28) | ((Addr) << 16) | (Count))
53
54#define NVE26E_CH_OPCODE_IMM(addr, value) \
55 /* op, addr, count */ \
56 ((4UL << 28) | ((addr) << 16) | (value))
57
58#define NVE26E_CH_OPCODE_GATHER(off, ins, type, cnt) \
59 /* op, offset, insert, type, count */ \
60 ((6UL << 28) | ((off) << 16) | ((ins) << 15) | ((type) << 14) | cnt)
61
62/* AVP OS methods */
63#define NVE276_NOP (0x00000080)
64#define NVE276_SET_APP_TIMEOUT (0x00000084)
65#define NVE276_SET_MICROCODE_A (0x00000085)
66#define NVE276_SET_MICROCODE_B (0x00000086)
67#define NVE276_SET_MICROCODE_C (0x00000087)
68
69/* Interrupt codes through inbox/outbox data codes (cpu->avp or avp->cpu) */
70#define NVE276_OS_INTERRUPT_NOP (0x00000000) /* wake up avp */
71#define NVE276_OS_INTERRUPT_TIMEOUT (0x00000001)
72#define NVE276_OS_INTERRUPT_SEMAPHORE_AWAKEN (0x00000002)
73#define NVE276_OS_INTERRUPT_EXECUTE_AWAKEN (0x00000004)
74#define NVE276_OS_INTERRUPT_DEBUG_STRING (0x00000008)
75#define NVE276_OS_INTERRUPT_DH_KEYEXCHANGE (0x00000010)
76#define NVE276_OS_INTERRUPT_APP_NOTIFY (0x00000020)
77#define NVE276_OS_INTERRUPT_VIDEO_IDLE (0x00000040)
78#define NVE276_OS_INTERRUPT_AUDIO_IDLE (0x00000080)
79#define NVE276_OS_INTERRUPT_AVP_BREAKPOINT (0x00800000)
80#define NVE276_OS_INTERRUPT_AVP_FATAL_ERROR (0x01000000)
81
82struct nvavp_os_info {
83 u32 entry_offset;
84 u32 control_offset;
85 u32 debug_offset;
86
87 struct nvmap_handle_ref *handle;
88 void *data;
89 u32 size;
90 phys_addr_t phys;
91 void *os_bin;
92 phys_addr_t reset_addr;
93};
94
95struct nvavp_ucode_info {
96 struct nvmap_handle_ref *handle;
97 void *data;
98 u32 size;
99 phys_addr_t phys;
100 void *ucode_bin;
101};
102
103#endif /* __MEDIA_VIDEO_TEGRA_NVAVP_OS_H */
diff --git a/drivers/media/video/tegra/ov14810.c b/drivers/media/video/tegra/ov14810.c
new file mode 100644
index 00000000000..2efd283b32b
--- /dev/null
+++ b/drivers/media/video/tegra/ov14810.c
@@ -0,0 +1,1390 @@
1/*
2 * ov14810.c - ov14810 sensor driver
3 *
4 * Copyright (c) 2011-2012, NVIDIA, All Rights Reserved.
5 *
6 * Contributors:
7 * Krupal Divvela <kdivvela@nvidia.com>
8 *
9 * This file is licensed under the terms of the GNU General Public License
10 * version 2. This program is licensed "as is" without any warranty of any
11 * kind, whether express or implied.
12 */
13
14#include <linux/delay.h>
15#include <linux/fs.h>
16#include <linux/i2c.h>
17#include <linux/miscdevice.h>
18#include <linux/slab.h>
19#include <linux/uaccess.h>
20#include <media/ov14810.h>
21#include <linux/module.h>
22#include <linux/moduleparam.h>
23
24
25#define OV14810_I2C_WRITE8(ADDR, OFFSET, VAL) do { \
26 if (0 != ov14810_write8(ADDR, OFFSET, VAL)) \
27 return 1; \
28 } while(0)
29
30#define OV14810_FRAME_LENGTH_REG_ADDR0 0x380e
31#define OV14810_FRAME_LENGTH_REG_ADDR1 0x380f
32
33#define OV14810_COARSE_TIME_REG_ADDR0 0x3500
34#define OV14810_COARSE_TIME_REG_ADDR1 0x3501
35#define OV14810_COARSE_TIME_REG_ADDR2 0x3502
36
37#define OV14810_GAIN_REG_ADDR0 0x350b
38
39#define OV14810_GROUP_ACCESS_REG_ADDR 0x3212
40
41static u8 uCProgram[] = {
42 0x02,0x03,0x6E,0x02,0x19,0x74,0xBB,0x01,0x06,0x89,0x82,0x8A,0x83,0xE0,0x22,0x50
43,0x02,0xE7,0x22,0xBB,0xFE,0x02,0xE3,0x22,0x89,0x82,0x8A,0x83,0xE4,0x93,0x22,0xBB
44,0x01,0x0C,0xE5,0x82,0x29,0xF5,0x82,0xE5,0x83,0x3A,0xF5,0x83,0xE0,0x22,0x50,0x06
45,0xE9,0x25,0x82,0xF8,0xE6,0x22,0xBB,0xFE,0x06,0xE9,0x25,0x82,0xF8,0xE2,0x22,0xE5
46,0x82,0x29,0xF5,0x82,0xE5,0x83,0x3A,0xF5,0x83,0xE4,0x93,0x22,0xBB,0x01,0x06,0x89
47,0x82,0x8A,0x83,0xF0,0x22,0x50,0x02,0xF7,0x22,0xBB,0xFE,0x01,0xF3,0x22,0xEF,0x8D
48,0xF0,0xA4,0xA8,0xF0,0xCF,0x8C,0xF0,0xA4,0x28,0xCE,0x8D,0xF0,0xA4,0x2E,0xFE,0x22
49,0xBC,0x00,0x0B,0xBE,0x00,0x29,0xEF,0x8D,0xF0,0x84,0xFF,0xAD,0xF0,0x22,0xE4,0xCC
50,0xF8,0x75,0xF0,0x08,0xEF,0x2F,0xFF,0xEE,0x33,0xFE,0xEC,0x33,0xFC,0xEE,0x9D,0xEC
51,0x98,0x40,0x05,0xFC,0xEE,0x9D,0xFE,0x0F,0xD5,0xF0,0xE9,0xE4,0xCE,0xFD,0x22,0xED
52,0xF8,0xF5,0xF0,0xEE,0x84,0x20,0xD2,0x1C,0xFE,0xAD,0xF0,0x75,0xF0,0x08,0xEF,0x2F
53,0xFF,0xED,0x33,0xFD,0x40,0x07,0x98,0x50,0x06,0xD5,0xF0,0xF2,0x22,0xC3,0x98,0xFD
54,0x0F,0xD5,0xF0,0xEA,0x22,0xC2,0xD5,0xEC,0x30,0xE7,0x09,0xB2,0xD5,0xE4,0xC3,0x9D
55,0xFD,0xE4,0x9C,0xFC,0xEE,0x30,0xE7,0x15,0xB2,0xD5,0xE4,0xC3,0x9F,0xFF,0xE4,0x9E
56,0xFE,0x12,0x00,0x70,0xC3,0xE4,0x9D,0xFD,0xE4,0x9C,0xFC,0x80,0x03,0x12,0x00,0x70
57,0x30,0xD5,0x07,0xC3,0xE4,0x9F,0xFF,0xE4,0x9E,0xFE,0x22,0xC5,0xF0,0xF8,0xA3,0xE0
58,0x28,0xF0,0xC5,0xF0,0xF8,0xE5,0x82,0x15,0x82,0x70,0x02,0x15,0x83,0xE0,0x38,0xF0
59,0x22,0xBB,0x01,0x0A,0x89,0x82,0x8A,0x83,0xE0,0xF5,0xF0,0xA3,0xE0,0x22,0x50,0x06
60,0x87,0xF0,0x09,0xE7,0x19,0x22,0xBB,0xFE,0x07,0xE3,0xF5,0xF0,0x09,0xE3,0x19,0x22
61,0x89,0x82,0x8A,0x83,0xE4,0x93,0xF5,0xF0,0x74,0x01,0x93,0x22,0xBB,0x01,0x10,0xE5
62,0x82,0x29,0xF5,0x82,0xE5,0x83,0x3A,0xF5,0x83,0xE0,0xF5,0xF0,0xA3,0xE0,0x22,0x50
63,0x09,0xE9,0x25,0x82,0xF8,0x86,0xF0,0x08,0xE6,0x22,0xBB,0xFE,0x0A,0xE9,0x25,0x82
64,0xF8,0xE2,0xF5,0xF0,0x08,0xE2,0x22,0xE5,0x83,0x2A,0xF5,0x83,0xE9,0x93,0xF5,0xF0
65,0xA3,0xE9,0x93,0x22,0xE8,0x8F,0xF0,0xA4,0xCC,0x8B,0xF0,0xA4,0x2C,0xFC,0xE9,0x8E
66,0xF0,0xA4,0x2C,0xFC,0x8A,0xF0,0xED,0xA4,0x2C,0xFC,0xEA,0x8E,0xF0,0xA4,0xCD,0xA8
67,0xF0,0x8B,0xF0,0xA4,0x2D,0xCC,0x38,0x25,0xF0,0xFD,0xE9,0x8F,0xF0,0xA4,0x2C,0xCD
68,0x35,0xF0,0xFC,0xEB,0x8E,0xF0,0xA4,0xFE,0xA9,0xF0,0xEB,0x8F,0xF0,0xA4,0xCF,0xC5
69,0xF0,0x2E,0xCD,0x39,0xFE,0xE4,0x3C,0xFC,0xEA,0xA4,0x2D,0xCE,0x35,0xF0,0xFD,0xE4
70,0x3C,0xFC,0x22,0x75,0xF0,0x08,0x75,0x82,0x00,0xEF,0x2F,0xFF,0xEE,0x33,0xFE,0xCD
71,0x33,0xCD,0xCC,0x33,0xCC,0xC5,0x82,0x33,0xC5,0x82,0x9B,0xED,0x9A,0xEC,0x99,0xE5
72,0x82,0x98,0x40,0x0C,0xF5,0x82,0xEE,0x9B,0xFE,0xED,0x9A,0xFD,0xEC,0x99,0xFC,0x0F
73,0xD5,0xF0,0xD6,0xE4,0xCE,0xFB,0xE4,0xCD,0xFA,0xE4,0xCC,0xF9,0xA8,0x82,0x22,0xB8
74,0x00,0xC1,0xB9,0x00,0x59,0xBA,0x00,0x2D,0xEC,0x8B,0xF0,0x84,0xCF,0xCE,0xCD,0xFC
75,0xE5,0xF0,0xCB,0xF9,0x78,0x18,0xEF,0x2F,0xFF,0xEE,0x33,0xFE,0xED,0x33,0xFD,0xEC
76,0x33,0xFC,0xEB,0x33,0xFB,0x10,0xD7,0x03,0x99,0x40,0x04,0xEB,0x99,0xFB,0x0F,0xD8
77,0xE5,0xE4,0xF9,0xFA,0x22,0x78,0x18,0xEF,0x2F,0xFF,0xEE,0x33,0xFE,0xED,0x33,0xFD
78,0xEC,0x33,0xFC,0xC9,0x33,0xC9,0x10,0xD7,0x05,0x9B,0xE9,0x9A,0x40,0x07,0xEC,0x9B
79,0xFC,0xE9,0x9A,0xF9,0x0F,0xD8,0xE0,0xE4,0xC9,0xFA,0xE4,0xCC,0xFB,0x22,0x75,0xF0
80,0x10,0xEF,0x2F,0xFF,0xEE,0x33,0xFE,0xED,0x33,0xFD,0xCC,0x33,0xCC,0xC8,0x33,0xC8
81,0x10,0xD7,0x07,0x9B,0xEC,0x9A,0xE8,0x99,0x40,0x0A,0xED,0x9B,0xFD,0xEC,0x9A,0xFC
82,0xE8,0x99,0xF8,0x0F,0xD5,0xF0,0xDA,0xE4,0xCD,0xFB,0xE4,0xCC,0xFA,0xE4,0xC8,0xF9
83,0x22,0xEB,0x9F,0xF5,0xF0,0xEA,0x9E,0x42,0xF0,0xE9,0x9D,0x42,0xF0,0xE8,0x9C,0x45
84,0xF0,0x22,0xE8,0x60,0x0F,0xEC,0xC3,0x13,0xFC,0xED,0x13,0xFD,0xEE,0x13,0xFE,0xEF
85,0x13,0xFF,0xD8,0xF1,0x22,0xE8,0x60,0x0F,0xEF,0xC3,0x33,0xFF,0xEE,0x33,0xFE,0xED
86,0x33,0xFD,0xEC,0x33,0xFC,0xD8,0xF1,0x22,0xE0,0xFC,0xA3,0xE0,0xFD,0xA3,0xE0,0xFE
87,0xA3,0xE0,0xFF,0x22,0xE0,0xF8,0xA3,0xE0,0xF9,0xA3,0xE0,0xFA,0xA3,0xE0,0xFB,0x22
88,0xEC,0xF0,0xA3,0xED,0xF0,0xA3,0xEE,0xF0,0xA3,0xEF,0xF0,0x22,0xE0,0xFB,0xA3,0xE0
89,0xFA,0xA3,0xE0,0xF9,0x22,0xF8,0xE0,0xFB,0xA3,0xA3,0xE0,0xF9,0x25,0xF0,0xF0,0xE5
90,0x82,0x15,0x82,0x70,0x02,0x15,0x83,0xE0,0xFA,0x38,0xF0,0x22,0xEB,0xF0,0xA3,0xEA
91,0xF0,0xA3,0xE9,0xF0,0x22,0xD0,0x83,0xD0,0x82,0xF8,0xE4,0x93,0x70,0x12,0x74,0x01
92,0x93,0x70,0x0D,0xA3,0xA3,0x93,0xF8,0x74,0x01,0x93,0xF5,0x82,0x88,0x83,0xE4,0x73
93,0x74,0x02,0x93,0x68,0x60,0xEF,0xA3,0xA3,0xA3,0x80,0xDF,0x8A,0x83,0x89,0x82,0xE4
94,0x73,0xEC,0x8E,0xF0,0xA4,0xCC,0xC5,0xF0,0xCC,0xCD,0xF8,0xEF,0xA4,0xCE,0xC5,0xF0
95,0x2D,0xFD,0xE4,0x3C,0xFC,0xE8,0xA4,0x2E,0xC8,0xC5,0xF0,0x3D,0xFD,0xE4,0x3C,0xFC
96,0xEF,0xA4,0xFF,0xE5,0xF0,0x28,0xFE,0xE4,0x3D,0xFD,0xE4,0x3C,0xFC,0x22,0x78,0x7F
97,0xE4,0xF6,0xD8,0xFD,0x75,0x81,0x7F,0x02,0x03,0xB5,0x02,0x17,0x7F,0xE4,0x93,0xA3
98,0xF8,0xE4,0x93,0xA3,0x40,0x03,0xF6,0x80,0x01,0xF2,0x08,0xDF,0xF4,0x80,0x29,0xE4
99,0x93,0xA3,0xF8,0x54,0x07,0x24,0x0C,0xC8,0xC3,0x33,0xC4,0x54,0x0F,0x44,0x20,0xC8
100,0x83,0x40,0x04,0xF4,0x56,0x80,0x01,0x46,0xF6,0xDF,0xE4,0x80,0x0B,0x01,0x02,0x04
101,0x08,0x10,0x20,0x40,0x80,0x90,0x03,0xFA,0xE4,0x7E,0x01,0x93,0x60,0xBC,0xA3,0xFF
102,0x54,0x3F,0x30,0xE5,0x09,0x54,0x1F,0xFE,0xE4,0x93,0xA3,0x60,0x01,0x0E,0xCF,0x54
103,0xC0,0x25,0xE0,0x60,0xA8,0x40,0xB8,0xE4,0x93,0xA3,0xFA,0xE4,0x93,0xA3,0xF8,0xE4
104,0x93,0xA3,0xC8,0xC5,0x82,0xC8,0xCA,0xC5,0x83,0xCA,0xF0,0xA3,0xC8,0xC5,0x82,0xC8
105,0xCA,0xC5,0x83,0xCA,0xDF,0xE9,0xDE,0xE7,0x80,0xBE,0x41,0x1B,0x5F,0x00,0x60,0x26
106,0x1B,0x23,0x07,0x83,0x07,0xE6,0x08,0x0D,0x1F,0x5D,0x1F,0x98,0x07,0x5F,0x04,0x73
107,0xFC,0x18,0x03,0xE8,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x01,0x00,0x0B
108,0x00,0x01,0x00,0x04,0x00,0xA0,0x00,0x64,0xC1,0x45,0xC1,0x46,0xC1,0x48,0xC1,0x47
109,0x00,0xE4,0xFD,0xFC,0xC2,0x8D,0xC2,0xA9,0xD2,0x8C,0xED,0x6F,0x70,0x02,0xEC,0x6E
110,0x60,0x0C,0x30,0x8D,0xFD,0x0D,0xBD,0x00,0x01,0x0C,0xC2,0x8D,0x80,0xEC,0xC2,0x8C
111,0x22,0xC2,0x8C,0xC2,0xA9,0x53,0x89,0xF0,0x43,0x89,0x02,0x75,0x8C,0x9C,0x75,0x8A
112,0x9C,0xC2,0x8D,0x22,0xD0,0xE0,0xD0,0xE0,0xE4,0xC0,0xE0,0xC0,0xE0,0x32,0x22,0x02
113,0xFF,0xFC,0x22,0x42,0x30,0x00,0x47,0x30,0x03,0x47,0x30,0x0C,0x41,0x30,0x18,0x42
114,0x30,0x1B,0x41,0x30,0x1E,0x41,0x30,0x20,0x41,0x31,0x06,0x41,0x35,0x03,0x42,0x36
115,0x00,0x42,0x36,0x03,0x42,0x36,0x0A,0x41,0x36,0x0F,0x41,0x36,0x11,0x41,0x36,0x13
116,0x41,0x36,0x15,0x44,0x37,0x02,0x43,0x37,0x07,0x41,0x37,0x0E,0x42,0x37,0x10,0x42
117,0x37,0x14,0x43,0x37,0x17,0x44,0x37,0x1B,0x45,0x37,0x22,0x44,0x38,0x08,0x41,0x38
118,0x19,0x41,0x3B,0x09,0x41,0x3C,0x01,0x41,0x40,0x00,0x44,0x40,0x02,0x41,0x40,0x09
119,0x41,0x40,0x0C,0x41,0x40,0x4F,0x43,0x43,0x00,0x48,0x47,0x00,0x41,0x47,0x09,0x42
120,0x47,0x0B,0x42,0x48,0x00,0x41,0x48,0x03,0x41,0x48,0x06,0x41,0x48,0x37,0x41,0x48
121,0x42,0x41,0x48,0x4A,0x42,0x50,0x00,0x41,0x50,0x1F,0x41,0x50,0x25,0x42,0x50,0x3B
122,0x41,0x50,0x41,0x41,0x50,0x43,0x41,0x5B,0x01,0x41,0x5B,0x03,0x42,0x38,0x2C,0x41
123,0x01,0x00,0x41,0x32,0x12,0x41,0x30,0x13,0x41,0x36,0x02,0x41,0x36,0x05,0x42,0x36
124,0x0C,0x41,0x36,0x14,0x44,0x37,0x0A,0x41,0x37,0x0F,0x41,0x37,0x13,0x41,0x37,0x16
125,0x41,0x37,0x21,0x42,0x37,0x27,0x45,0x38,0x03,0x46,0x38,0x0C,0x42,0x38,0x17,0x46
126,0x38,0x1C,0x42,0x38,0x2C,0x41,0x40,0x01,0x42,0x40,0x50,0x41,0x40,0x53,0x41,0x50
127,0x02,0x41,0x50,0x3D,0x41,0x50,0x42,0x41,0x50,0x47,0x41,0x59,0x01,0xEF,0xFF,0xFF
128,0x41,0x32,0x12,0x41,0x32,0x12,0x84,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x09
129,0x00,0xA7,0xA0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x04,0xE0,0xF8
130,0xF0,0x01,0x05,0x03,0x2D,0x1F,0x20,0x80,0x2E,0x00,0x24,0x6C,0x84,0x13,0x20,0x3D
131,0x28,0xD1,0x73,0x01,0x00,0x04,0x40,0x16,0x5F,0x58,0x80,0x11,0x11,0xA0,0x46,0x40
132,0x2C,0x1A,0x30,0x2E,0x2E,0x70,0x00,0x40,0x00,0xF0,0x80,0x0A,0x80,0x29,0xC5,0x08
133,0x02,0x10,0x40,0x00,0xFF,0xFF,0x00,0xF0,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00
134,0x00,0x00,0x00,0x04,0x0F,0x50,0x80,0x1B,0x01,0x00,0x5F,0x4E,0x00,0x10,0x01,0x10
135,0x0E,0x08,0x03,0x00,0x02,0x02,0x00,0x00,0x1F,0x53,0x11,0x42,0x13,0x0F,0x83,0x00
136,0x04,0x81,0x00,0x57,0xB6,0x08,0x66,0x02,0x07,0x02,0x88,0x01,0xE6,0x0F,0xA0,0x01
137,0xF4,0x22,0x02,0x24,0x4A,0x32,0xAC,0x07,0xA4,0x03,0xA0,0x10,0x10,0x00,0xC0,0x00
138,0xA1,0x00,0x00,0x21,0x00,0x00,0xFF,0xFF,0x10,0xA0,0x02,0x88,0x01,0xE6,0xFF,0xFF
139,0xFF,0xFF,0xFF,0x00,0x00,0x09,0x00,0xA7,0xA0,0x08,0x00,0x00,0x00,0x00,0x00,0x00
140,0x00,0x00,0x40,0x04,0xE0,0xF8,0xF0,0x01,0x05,0x03,0x2D,0x1F,0x20,0x80,0x2E,0x00
141,0x24,0x6C,0x84,0x13,0x20,0x3D,0x28,0xD1,0x73,0x01,0x00,0x04,0x40,0x16,0x5F,0x58
142,0x80,0x11,0x11,0xA0,0x46,0x40,0x2C,0x1A,0x30,0x2E,0x2E,0x70,0x00,0x40,0x00,0xF0
143,0x80,0x0A,0x80,0x29,0xC5,0x08,0x02,0x10,0x40,0x00,0xFF,0xFF,0x00,0xF0,0x04,0x01
144,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0F,0x50,0x80,0x1B,0x01,0x00
145,0x5F,0x4E,0x00,0x10,0x01,0x10,0x0E,0x08,0x03,0x00,0x02,0x02,0x00,0x00,0x1F,0x42
146,0x11,0x42,0x13,0x30,0x80,0x00,0x84,0x01,0x61,0xF6,0x17,0x08,0x66,0x0C,0x0B,0x11
147,0x40,0x0C,0xF0,0x1F,0x00,0x0D,0x08,0x44,0x96,0x24,0x40,0x30,0x0C,0x0C,0xFC,0x00
148,0x08,0x04,0x04,0x02,0xC0,0x00,0xA1,0x00,0x00,0x21,0x00,0x00,0xFF,0xFF,0x10,0xA0
149,0x11,0x40,0x0C,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x09,0x00,0xA7,0xA0,0x08
150,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x04,0xE0,0xF8,0xF0,0x01,0x05,0x03
151,0x2D,0x1F,0x20,0x80,0x2E,0x00,0x24,0x6C,0x84,0x13,0x20,0x3D,0x28,0xD1,0x73,0x01
152,0x00,0x04,0x40,0x16,0x5F,0x58,0x80,0x11,0x11,0xA0,0x46,0x40,0x2C,0x1A,0x30,0x2E
153,0x2E,0x70,0x00,0x40,0x00,0xF0,0x80,0x0A,0x80,0x29,0xC5,0x08,0x02,0x10,0x40,0x00
154,0xFF,0xFF,0x00,0xF0,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04
155,0x0F,0x50,0x80,0x1B,0x01,0x00,0x5F,0x4E,0x00,0x10,0x01,0x10,0x0E,0x08,0x03,0x00
156,0x02,0x02,0x00,0x00,0x1F,0x42,0x11,0x42,0x13,0x30,0x80,0x00,0x84,0x01,0x61,0xF6
157,0x17,0x08,0x66,0x0C,0x0B,0x02,0x88,0x01,0xE6,0x0A,0x40,0x01,0xFC,0x44,0x96,0x24
158,0x40,0x35,0x85,0x01,0xF2,0x07,0x6C,0x04,0x04,0x02,0xC0,0x00,0xA1,0x00,0x00,0x31
159,0x00,0x00,0xFF,0xFF,0x10,0xA0,0x02,0x88,0x01,0xE6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
160,0x00,0x05,0x6D,0x07,0x18,0x06,0x13,0xFF,0x05,0x06,0xB9,0xFF,0xFF,0xFF,0xFF,0xFF
161,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
162,0xFF,0xFF,0xFF,0x01,0x0D,0x4C,0x02,0x08,0xB9,0x03,0x0F,0xF5,0x05,0x0D,0xC7,0x0A
163,0x14,0x6D,0x0B,0x14,0xB6,0x0C,0x0F,0xD2,0x0D,0x14,0xED,0x0F,0x15,0x59,0x10,0x15
164,0x5D,0x14,0x15,0x70,0x18,0x11,0xAF,0x19,0x12,0x79,0x1F,0x15,0x61,0x20,0x17,0x29
165,0x22,0x14,0x06,0x23,0x14,0x2D,0x29,0x18,0xAF,0x2A,0x10,0x9F,0x39,0x17,0x9F,0x3B
166,0x0E,0xA6,0x3C,0x17,0xEB,0x4A,0x18,0x92,0x4B,0x14,0x88,0x50,0x17,0x42,0x57,0x15
167,0x61,0x59,0x11,0x3D,0x60,0x17,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
168,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x22,0xA2,0xC1,0xCC,0xC1,0xCB,0x25,0x11,0x26,0x88
169,0x60,0x00,0x64,0x45,0x30,0x03,0x41,0x01,0x00,0x60,0x00,0x64,0x41,0x01,0x00,0xEF
170,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0B,0x02,0xF7
171,0x00,0x00,0x00,0x00,0x00,0x04,0x14,0x28,0x36,0x64,0x04,0x00,0x09,0x00,0x9D,0xC3
172,0x0D,0x01,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
173,0x90,0x1B,0x23,0x12,0x18,0x70,0x90,0x1B,0x68,0x12,0x03,0x0C,0x90,0x1B,0x68,0xF1
174,0xE3,0xFF,0xF4,0x60,0x34,0xEF,0x14,0xB5,0xC5,0x23,0x75,0xC5,0xFE,0xE4,0xFD,0x7F
175,0x8E,0x11,0x89,0x90,0x1B,0x68,0x12,0x02,0xEC,0x90,0x00,0x01,0x12,0x01,0x3C,0xAA
176,0xF0,0xF9,0x12,0x03,0x3B,0x7D,0x04,0x7F,0x8E,0x11,0x89,0x80,0x0F,0x90,0x1B,0x69
177,0xE4,0x75,0xF0,0x03,0x12,0x00,0xFB,0x80,0xC3,0x75,0xC1,0x06,0x75,0xC5,0xFF,0x22
178,0xFD,0x7F,0x20,0x11,0x89,0xE4,0xFD,0x7F,0x12,0x8F,0xFA,0x8D,0xFB,0xE4,0xF5,0xF8
179,0x90,0x1B,0x35,0xE0,0xFE,0xA3,0xE0,0xFF,0x43,0xF8,0x01,0xEF,0x4E,0x70,0x08,0xE5
180,0xF9,0x64,0x0F,0x60,0x13,0x80,0xF8,0xE5,0xF9,0x64,0x0F,0x60,0x0B,0xEF,0x1F,0xAC
181,0x06,0x70,0x01,0x1E,0x4C,0x70,0xF0,0x22,0x22,0xAF,0xC1,0xEF,0x14,0x60,0x15,0x24
182,0xFE,0x60,0x3E,0x24,0x03,0x70,0x63,0xE5,0xC2,0xB4,0x01,0x06,0x12,0x17,0x92,0x02
183,0x04,0x64,0x80,0x56,0xE5,0xC2,0x64,0x01,0x70,0x25,0x31,0x35,0xE4,0xFD,0x7F,0x20
184,0x11,0x89,0x7D,0x03,0x7F,0x12,0x11,0x89,0x7D,0x07,0x7F,0x14,0x11,0x89,0x7D,0x03
185,0x7F,0x13,0x11,0x89,0x75,0xC5,0xFF,0xE4,0xF5,0xC1,0xFD,0x7F,0x18,0x80,0x8A,0x80
186,0x29,0xE5,0xC2,0x70,0x12,0x31,0x35,0x7F,0x20,0xB1,0x22,0x90,0x1B,0x5F,0xEF,0xF0
187,0xE4,0x11,0x80,0x7D,0x03,0x80,0x0D,0xE5,0xC2,0xB4,0x01,0x0C,0x90,0x1B,0x5F,0xE0
188,0x11,0x80,0xE4,0xFD,0x7F,0x13,0xA1,0xAD,0x80,0x00,0x75,0xC1,0x01,0x22,0xE4,0xFD
189,0xFF,0x7E,0x01,0x80,0x0E,0x31,0x2E,0x7F,0x0A,0x7E,0x00,0x02,0x04,0x31,0xFD,0x7F
190,0x02,0x7E,0x35,0xAB,0x07,0xAA,0x06,0xEA,0xF5,0xFA,0xEB,0xF5,0xFB,0x8D,0xFC,0x75
191,0xF8,0x10,0x01,0x90,0xE4,0xFD,0x7F,0x12,0x7E,0x32,0x31,0x43,0xAD,0x43,0xAC,0x42
192,0x7F,0x00,0x7E,0x35,0x31,0x84,0xE5,0x45,0x31,0x3E,0xAD,0x49,0xAC,0x48,0x7F,0x0A
193,0x7E,0x35,0x31,0x84,0x7D,0x10,0x7F,0x12,0x7E,0x32,0x31,0x43,0x7D,0xA0,0x7F,0x12
194,0x7E,0x32,0x80,0xBF,0x8E,0x31,0x8F,0x32,0x8C,0x33,0x8D,0x34,0xE5,0x33,0xFD,0x31
195,0x43,0xE5,0x32,0x24,0x01,0xFF,0xE4,0x35,0x31,0xFE,0xAD,0x34,0x80,0xA5,0x8E,0x2F
196,0x8F,0x30,0x90,0x1B,0x10,0xE0,0xFF,0x90,0x1B,0x0F,0xE0,0xFD,0x12,0x18,0x35,0xAA
197,0x06,0xA9,0x07,0x7B,0xFF,0x90,0x1B,0x4E,0x12,0x03,0x0C,0x90,0x00,0x80,0x12,0x00
198,0x1F,0xFE,0x90,0x00,0x81,0x12,0x00,0x1F,0x7C,0x00,0x90,0x1B,0x5B,0xB1,0x18,0x90
199,0x00,0x82,0x12,0x00,0x1F,0xFE,0x90,0x00,0x83,0x12,0x00,0x1F,0x90,0x1B,0x5D,0xB1
200,0x18,0xB1,0x05,0x7C,0x41,0x7D,0x1A,0x12,0x03,0x41,0x7B,0x00,0x7A,0x71,0x79,0x02
201,0x78,0x00,0x12,0x01,0xFF,0x90,0x1B,0x51,0xEE,0xF0,0xA3,0xEF,0xF0,0xAE,0x2F,0xAF
202,0x30,0x7C,0x27,0x7D,0x10,0x12,0x03,0x41,0xC0,0x06,0xC0,0x07,0x90,0x1B,0x51,0xE0
203,0xFE,0xA3,0xE0,0xFB,0xAA,0x06,0xE4,0xF9,0xF8,0xD0,0x07,0xD0,0x06,0x12,0x01,0xFF
204,0x90,0x1B,0x53,0x12,0x02,0xE0,0xB1,0x05,0xE4,0xFC,0xFD,0x90,0x1B,0x53,0x12,0x02
205,0xD4,0x12,0x01,0x74,0xE4,0x7B,0x20,0xFA,0xF9,0xF8,0x12,0x01,0x74,0xE4,0x7B,0xE0
206,0x7A,0x2E,0xF9,0xF8,0x12,0x01,0xFF,0x90,0x1B,0x57,0x12,0x02,0xE0,0x90,0x1B,0x57
207,0x12,0x02,0xC8,0x78,0x08,0x12,0x02,0xA2,0x90,0x1B,0x11,0xEE,0xF0,0xA3,0xEF,0xF0
208,0x90,0x1B,0x57,0x12,0x02,0xC8,0xE4,0x90,0x1B,0x13,0xEF,0xF0,0x7F,0x18,0x7E,0x38
209,0xB1,0x3A,0xEF,0x30,0xE0,0x0D,0x51,0xD8,0x78,0x01,0x12,0x02,0xA2,0x90,0x1B,0x53
210,0x12,0x02,0xE0,0x51,0xD8,0xEF,0x54,0xF0,0xFF,0xE4,0xF5,0x44,0x8F,0x45,0x51,0xD8
211,0x78,0x08,0x12,0x02,0xA2,0xE4,0x8E,0x42,0x8F,0x43,0x51,0xD8,0x78,0x04,0x12,0x02
212,0xA2,0xF1,0x35,0x90,0x1B,0x5E,0xE0,0x24,0xF8,0xFF,0x90,0x1B,0x5D,0xE0,0x34,0xFF
213,0xFE,0xE4,0xFC,0xFD,0xD3,0x12,0x02,0x91,0x40,0x10,0x51,0xD8,0x78,0x04,0x12,0x02
214,0xA2,0xEF,0x24,0x08,0xFD,0xE4,0x3E,0xFC,0x80,0x08,0x90,0x1B,0x5D,0xE0,0xFC,0xA3
215,0xE0,0xFD,0x7F,0x0E,0x7E,0x38,0x21,0x84,0x90,0x1B,0x53,0x02,0x02,0xC8,0x90,0x1B
216,0x2F,0xE0,0xFE,0xA3,0xE0,0xFF,0x90,0x1B,0x49,0x12,0x02,0xEC,0xAC,0x02,0xAD,0x01
217,0x8E,0x33,0x8F,0x34,0x8C,0x35,0x8D,0x36,0x8F,0x82,0x8E,0x83,0xE4,0x93,0x91,0xFC
218,0x70,0x02,0x05,0x33,0x90,0x1B,0x4C,0xE0,0xFF,0xF4,0x70,0x02,0x81,0x19,0xEF,0x54
219,0xE0,0xFB,0x70,0x24,0xE0,0x54,0x1F,0xB1,0x0E,0x05,0x34,0xE5,0x34,0x70,0x02,0x05
220,0x33,0xF5,0x82,0x85,0x33,0x83,0xE4,0x93,0x90,0x1B,0x4C,0xF0,0x60,0xEB,0x05,0x34
221,0xE5,0x34,0x70,0x02,0x05,0x33,0x80,0xCC,0x90,0x1B,0x4C,0xE0,0x54,0x1F,0xA3,0xF0
222,0x90,0x1B,0x4C,0xEB,0xF0,0x64,0x20,0x60,0x0A,0xE0,0xFF,0x64,0x80,0x60,0x04,0xEF
223,0xB4,0xC0,0x15,0x91,0x2A,0xFF,0x90,0x1B,0x4E,0xE4,0xF0,0xA3,0xEF,0xF0,0x05,0x34
224,0xE5,0x34,0x70,0x02,0x05,0x33,0x80,0x19,0x91,0x2A,0xFF,0x74,0x01,0x93,0x90,0x1B
225,0x4E,0xCF,0xF0,0xA3,0xEF,0xF0,0x74,0x02,0x25,0x34,0xF5,0x34,0xE4,0x35,0x33,0xF5
226,0x33,0x90,0x1B,0x4C,0xE0,0xB4,0x60,0x08,0x91,0x33,0xFF,0x12,0x04,0x31,0x80,0x7F
227,0x90,0x1B,0x4C,0xE0,0xB4,0xE0,0x21,0xA3,0xE0,0xB4,0x02,0x16,0xAA,0x35,0xA9,0x36
228,0x7B,0xFF,0x12,0x01,0x11,0x85,0xF0,0x35,0xF5,0x36,0x91,0x33,0x8E,0x33,0xF5,0x34
229,0x80,0x5D,0x74,0x02,0xB1,0x0E,0x80,0x57,0x90,0x1B,0x4D,0xE0,0xD3,0x94,0x00,0x40
230,0x4E,0x90,0x1B,0x4C,0xE0,0xB4,0xC0,0x07,0x91,0x1A,0x12,0x18,0x7A,0x80,0x26,0x90
231,0x1B,0x4C,0xE0,0xB4,0x80,0x09,0x91,0x1A,0x7B,0x01,0x12,0x15,0x27,0x80,0x16,0x90
232,0x1B,0x4C,0xE0,0x90,0x1B,0x4E,0xB4,0x40,0x08,0xE0,0xFE,0x91,0x1D,0x31,0x43,0x80
233,0x04,0x91,0x1D,0x11,0x89,0x05,0x36,0xE5,0x36,0x70,0x02,0x05,0x35,0x90,0x1B,0x4E
234,0xE4,0x75,0xF0,0x01,0x12,0x00,0xFB,0x90,0x1B,0x4D,0xE0,0x14,0xF0,0x80,0xA9,0x91
235,0x2A,0x91,0xFC,0x70,0x02,0x05,0x33,0x61,0x04,0x22,0x90,0x1B,0x4E,0xA3,0xE0,0xFF
236,0x85,0x36,0x82,0x85,0x35,0x83,0xE4,0x93,0xFD,0x22,0x85,0x34,0x82,0x85,0x33,0x83
237,0xE4,0x93,0x22,0x90,0x1B,0x4E,0xE0,0xFE,0xA3,0xE0,0x22,0xE4,0x90,0x1B,0x4E,0xF0
238,0xA3,0xF0,0x30,0x47,0x05,0x90,0x1B,0x01,0x80,0x03,0x90,0x1B,0x45,0xE0,0xFA,0xA3
239,0xE0,0xFB,0x90,0x1B,0x44,0xE0,0x2B,0xFE,0x90,0x1B,0x43,0xE0,0x3A,0x90,0x1B,0x50
240,0xF0,0xA3,0xCE,0xF0,0xA3,0xEA,0xF0,0xA3,0xEB,0xF0,0x30,0x48,0x6B,0xD2,0x45,0x30
241,0x47,0x53,0x91,0xF3,0x90,0x1B,0x43,0xE0,0xFE,0xA3,0xE0,0xFF,0xD3,0x94,0x00,0xEE
242,0x94,0x00,0x40,0x0A,0xEF,0x24,0x06,0xFF,0xE4,0x3E,0xFE,0x12,0x04,0x31,0x91,0x33
243,0xFF,0x90,0x1B,0x52,0xD1,0x25,0x40,0x54,0xB1,0x2C,0xC3,0x90,0x1B,0x38,0xE0,0x9F
244,0x90,0x1B,0x37,0xE0,0x9E,0x50,0x45,0x90,0x1B,0x39,0xA3,0xE0,0xFF,0xBF,0xFF,0x02
245,0x80,0x22,0x90,0x1B,0x37,0xF1,0xBE,0x90,0x1B,0x4D,0xE0,0x9F,0xFF,0x90,0x1B,0x4C
246,0xE0,0x9E,0xFE,0x80,0x24,0x91,0xF3,0x91,0x33,0xFF,0xA3,0xD1,0x25,0x40,0x1D,0xB1
247,0x2C,0x4E,0x60,0x18,0xF1,0xB2,0x80,0x11,0x91,0xF3,0x90,0x1B,0x50,0xE0,0xFE,0xA3
248,0xE0,0xFF,0x7C,0x00,0x7D,0x05,0x12,0x00,0x5E,0x12,0x04,0x31,0x31,0x37,0x53,0xCB
249,0xFB,0x21,0x2E,0xF1,0xAA,0x30,0x48,0x03,0x43,0xCB,0x04,0x22,0x90,0x1B,0x4C,0xF0
250,0x05,0x34,0xE5,0x34,0x22,0x90,0x1B,0x5B,0xE0,0xFE,0xA3,0xE0,0xFF,0x22,0x25,0x36
251,0xF5,0x36,0xE4,0x35,0x35,0xF5,0x35,0x22,0x24,0x00,0xFF,0xEC,0x3E,0xF0,0xA3,0xEF
252,0xF0,0x22,0x8F,0xFA,0x75,0xF8,0x02,0x11,0x90,0xAF,0xFB,0x22,0xED,0x9F,0xFF,0xEC
253,0x9E,0xFE,0x90,0x1B,0x4C,0xF0,0xA3,0xEF,0xF0,0x22,0xAD,0x07,0xAC,0x06,0xEC,0xF5
254,0xFA,0xED,0xF5,0xFB,0x75,0xF8,0x12,0x11,0x90,0xAF,0xFB,0x22,0x12,0x04,0x51,0x90
255,0x1B,0x25,0xF1,0xC5,0x90,0x1F,0xF8,0xE4,0x93,0xF4,0x70,0x4D,0x7F,0x05,0x7E,0x3D
256,0xB1,0x3A,0xEF,0x60,0x44,0x75,0x2F,0x3D,0x75,0x30,0x0E,0x75,0x31,0x1F,0x75,0x32
257,0x83,0xE4,0x90,0x1B,0x49,0xF0,0xB1,0xB3,0x70,0x02,0x05,0x31,0x05,0x30,0xE5,0x30
258,0x70,0x02,0x05,0x2F,0xD1,0x11,0x94,0x04,0x40,0xEC,0x75,0x31,0x1F,0x75,0x32,0xB8
259,0xE4,0x90,0x1B,0x49,0xF0,0xB1,0xB3,0x70,0x02,0x05,0x31,0x05,0x30,0xE5,0x30,0x70
260,0x02,0x05,0x2F,0xD1,0x11,0x94,0x1E,0x40,0xEC,0x7D,0x04,0x7F,0x8E,0x11,0x89,0xE4
261,0xF5,0xC1,0x22,0xAF,0x30,0xAE,0x2F,0xB1,0x3A,0xEF,0xF4,0x85,0x32,0x82,0x85,0x31
262,0x83,0xF0,0x05,0x32,0xE5,0x32,0x22,0x7F,0x03,0x7E,0x30,0xB1,0x3A,0x8F,0x2F,0x7F
263,0x06,0x7E,0x30,0xB1,0x3A,0x8F,0x30,0xAF,0xC1,0xEF,0x24,0xFC,0x60,0x12,0x24,0x02
264,0x70,0x1C,0x53,0x2F,0xFC,0x43,0x2F,0x01,0x53,0x30,0xDF,0x43,0x30,0x20,0x80,0x09
265,0x53,0x2F,0xFC,0x43,0x2F,0x02,0x53,0x30,0xDF,0xE4,0xF5,0xC1,0x80,0x03,0x75,0xC1
266,0x01,0xAD,0x2F,0x7F,0x03,0x7E,0x30,0x31,0x43,0xAD,0x30,0x7F,0x06,0x7E,0x30,0x21
267,0x43,0x90,0x1B,0x49,0xE0,0x04,0xF0,0xE0,0xC3,0x22,0x90,0x1B,0x41,0xE0,0xFE,0xA3
268,0xE0,0xFF,0x90,0x1B,0x3F,0xE0,0xFC,0xA3,0xE0,0xFD,0xD3,0x9F,0xEC,0x9E,0x22,0x30
269,0x47,0x22,0xD1,0x1A,0x40,0x11,0xED,0x9F,0xFF,0xEC,0x9E,0xFE,0x90,0x1B,0x02,0xE0
270,0x90,0x1B,0x01,0xF1,0x15,0x80,0x30,0xF1,0x0C,0x90,0x1B,0x02,0xE0,0x2F,0xFF,0x90
271,0x1B,0x01,0x80,0x23,0x30,0x48,0x27,0xD1,0x1A,0x40,0x11,0xED,0x9F,0xFF,0xEC,0x9E
272,0xFE,0x90,0x1B,0x46,0xE0,0x90,0x1B,0x45,0xF1,0x15,0x80,0x0B,0xF1,0x0C,0x90,0x1B
273,0x46,0xE0,0x2F,0xFF,0x90,0x1B,0x45,0xE0,0x3E,0x90,0x1B,0x4C,0x80,0x0B,0x90,0x1B
274,0x45,0xE0,0xFF,0xA3,0xE0,0x90,0x1B,0x4C,0xCF,0xF0,0xA3,0xEF,0xF0,0xF1,0xB2,0x31
275,0x9E,0x30,0x47,0x05,0x90,0x1B,0x03,0x80,0x03,0x90,0x1B,0x47,0xE0,0xFE,0xA3,0xE0
276,0xFF,0x12,0x15,0xB2,0x21,0x54,0x7D,0x01,0xAF,0xC1,0x12,0x18,0x35,0x12,0x19,0xB7
277,0x70,0x06,0xE9,0xF4,0x70,0x02,0xEA,0xF4,0x70,0x04,0x75,0xC1,0x01,0x22,0xD2,0x46
278,0x12,0x19,0x3B,0x90,0x1B,0x0F,0xE0,0x70,0x06,0x31,0x2E,0xF1,0x5C,0x51,0xDE,0x90
279,0x1B,0x0F,0x74,0x01,0xF0,0xA3,0xE5,0xC1,0xF0,0x30,0x47,0x05,0x90,0x1B,0x01,0x80
280,0x03,0x90,0x1B,0x45,0xE0,0xFF,0xA3,0xE0,0x90,0x1B,0x17,0xCF,0xF0,0xA3,0xEF,0xF0
281,0xD1,0x2F,0xE4,0x90,0x1B,0x19,0xF0,0x90,0x1B,0x14,0xE0,0xFF,0xA3,0xE0,0x90,0x1B
282,0x1A,0xCF,0xF0,0xA3,0xEF,0xF0,0x91,0x3B,0xE4,0xF5,0xC1,0x22,0x90,0x1B,0x3D,0xE0
283,0xFE,0xA3,0xE0,0xFF,0x22,0x2F,0xFF,0xE0,0x3E,0xFE,0x90,0x1B,0x3E,0xE0,0x2F,0xFF
284,0x90,0x1B,0x3D,0x22,0xE4,0x33,0x24,0x01,0xFF,0xE4,0x33,0xFE,0xE4,0x33,0xFD,0xE4
285,0x33,0xFC,0x12,0x01,0x74,0xA8,0x04,0xA9,0x05,0xAA,0x06,0xAB,0x07,0x22,0xAB,0x07
286,0xAA,0x06,0xB1,0x3A,0x90,0x1B,0x4C,0xEF,0xF0,0xEB,0x24,0x01,0xFF,0xE4,0x3A,0xFE
287,0xB1,0x3A,0xEF,0xFD,0x90,0x1B,0x4C,0xE0,0xFE,0xED,0xFF,0x22,0x7F,0x00,0x7E,0x35
288,0xF1,0x3E,0x90,0x1B,0x1D,0xEE,0xF0,0xA3,0xEF,0xF0,0x7F,0x02,0x7E,0x35,0xB1,0x3A
289,0x90,0x1B,0x1F,0xE4,0xF0,0xA3,0xEF,0xF0,0x7F,0x0A,0x7E,0x35,0xF1,0x3E,0x90,0x1B
290,0x21,0xEE,0xF0,0xA3,0xEF,0xF0,0x22,0x90,0x1B,0x1D,0xE0,0xFC,0xA3,0xE0,0xFD,0x7F
291,0x00,0x7E,0x35,0x31,0x84,0x90,0x1B,0x1F,0xA3,0xE0,0x31,0x3E,0x90,0x1B,0x21,0xE0
292,0xFC,0xA3,0xE0,0xFD,0x7F,0x0A,0x7E,0x35,0x21,0x84,0x7D,0x01,0x7F,0x00,0x7E,0x01
293,0x21,0x43,0x90,0x1B,0x4C,0xE0,0xFE,0xA3,0xE0,0xFF,0x22,0x90,0x1B,0x3B,0xE0,0xFE
294,0xA3,0xE0,0xFF,0xC3,0x22,0xE0,0xFE,0xA3,0xE0,0xFF,0xA3,0xE0,0xFC,0xA3,0xE0,0xFD
295,0x41,0xF0,0xE5,0xC1,0xC3,0x94,0xC1,0x50,0x06,0xAD,0xC4,0xAF,0xC1,0xA1,0xAD,0x75
296,0xC1,0x01,0x22,0x12,0x02,0xEC,0x02,0x00,0x06,0x7F,0x0A,0x7E,0x30,0xE1,0x3E,0x7F
297,0x2A,0x7E,0x30,0xA1,0x3A,0x90,0x1B,0x4B,0xE5,0xC1,0xF0,0xE4,0xF5,0xC1,0xE0,0x12
298,0x03,0x15,0x10,0x21,0x00,0x10,0x2B,0x01,0x10,0x40,0x02,0x10,0x52,0x03,0x10,0x5C
299,0x04,0x10,0x63,0x05,0x10,0x6A,0x07,0x10,0x7B,0x08,0x10,0x7F,0x09,0x00,0x00,0x10
300,0x88,0x75,0xC2,0x4B,0xE4,0xF5,0xC3,0x75,0xC4,0x01,0x22,0x12,0x0F,0xE9,0x11,0x8C
301,0x12,0x0F,0xEF,0x8F,0xC2,0x90,0x1B,0x49,0x11,0x98,0xF5,0xC3,0xED,0xF5,0xC4,0x22
302,0x75,0xC2,0x08,0xE4,0xFF,0x12,0x0D,0x22,0x8F,0xC3,0x7F,0x01,0x12,0x0D,0x22,0x8F
303,0xC4,0x22,0xE4,0xF5,0xC2,0x75,0xC3,0x2C,0x75,0xC4,0x38,0x22,0x75,0xC2,0x07,0xE4
304,0xF5,0xC3,0x22,0x75,0xC2,0x5D,0x75,0xC3,0xC0,0x22,0x7F,0x02,0x71,0x44,0x11,0x8C
305,0x90,0x1B,0x49,0x11,0x98,0xF5,0xC2,0xED,0xF5,0xC3,0x22,0x75,0xC2,0x0A,0x22,0x31
306,0x36,0x8F,0xC2,0x31,0x29,0x8F,0xC3,0x22,0x75,0xC1,0x01,0x22,0x90,0x1B,0x49,0xEE
307,0xF0,0xA3,0xEF,0xF0,0x22,0x90,0x1B,0x11,0xE0,0xFC,0xA3,0xE0,0xFD,0xEC,0x22,0xE4
308,0x90,0x1B,0x49,0xF0,0xA3,0xF0,0xA3,0xF0,0xA3,0xF0,0xAF,0xC1,0xEF,0x12,0x03,0x15
309,0x10,0xC9,0x00,0x10,0xD2,0x01,0x10,0xD7,0x05,0x10,0xDC,0x10,0x10,0xED,0x11,0x10
310,0xF6,0x15,0x11,0x00,0x20,0x00,0x00,0x11,0x08,0x11,0x95,0x31,0x21,0x90,0x1B,0x13
311,0x80,0x14,0x90,0x1B,0x14,0x80,0x19,0x90,0x1B,0x16,0x80,0x1D,0x90,0x1B,0x17,0x11
312,0x98,0x31,0x21,0x90,0x1B,0x19,0xE0,0x90,0x1B,0x4C,0xF0,0x80,0x21,0x90,0x1B,0x1A
313,0x11,0x98,0x31,0x21,0x80,0x18,0x90,0x1B,0x1C,0xE0,0x90,0x1B,0x4A,0xF0,0x80,0x0E
314,0x90,0x1B,0x49,0x74,0x04,0xF0,0x80,0x06,0x90,0x1B,0x49,0x74,0x01,0xF0,0x90,0x1B
315,0x49,0xE0,0xF5,0xC1,0xA3,0xE0,0xF5,0xC2,0xA3,0xE0,0xF5,0xC3,0xA3,0xE0,0xF5,0xC4
316,0x22,0x90,0x1B,0x4A,0xF0,0xED,0xA3,0xF0,0x22,0x7F,0x01,0x8F,0xFA,0x75,0xF8,0x22
317,0x12,0x08,0x90,0xAF,0xFB,0x22,0xE4,0xFF,0x31,0x2B,0x7E,0x00,0x22,0xE4,0xF5,0x2F
318,0xAF,0xC1,0xEF,0x14,0x60,0x11,0x14,0x60,0x18,0x14,0x60,0x15,0x14,0x60,0x17,0x24
319,0x04,0x70,0x1F,0x31,0x8B,0x80,0x1E,0x90,0x1B,0x64,0x11,0x98,0xFF,0x8F,0xC3,0x80
320,0x0C,0x75,0x2F,0x04,0x80,0x0F,0x90,0x1B,0x66,0x11,0x98,0xF5,0xC3,0xED,0xF5,0xC4
321,0x80,0x03,0x75,0x2F,0x01,0x85,0x2F,0xC1,0x22,0xE0,0x54,0x1F,0xFC,0xA3,0xE0,0xFD
322,0x7F,0x50,0x51,0x62,0x7F,0xE8,0x7E,0x03,0x12,0x04,0x31,0x71,0x3C,0xC3,0x33,0xCE
323,0x33,0xCE,0xD8,0xF9,0xFF,0x7C,0x00,0x7D,0x08,0x12,0x00,0xC5,0x90,0x1B,0x64,0xEE
324,0xF0,0xA3,0xEF,0xF0,0x71,0xAA,0x90,0x1B,0x66,0xEE,0xF0,0xA3,0xEF,0xF0,0x22,0x90
325,0x1B,0x2B,0xE0,0xFE,0xA3,0xE0,0x8E,0x2F,0xF5,0x30,0x8E,0x31,0xF5,0x32,0x90,0x1B
326,0x29,0x12,0x0F,0xC5,0xAF,0xC1,0xEF,0x24,0xFD,0x60,0x0B,0x04,0x70,0x10,0x74,0x36
327,0x51,0x58,0x74,0x38,0x80,0x0E,0x74,0x3A,0x51,0x58,0x74,0x3C,0x80,0x06,0x74,0x32
328,0x51,0x58,0x74,0x34,0x25,0x32,0xF5,0x32,0xE4,0x35,0x31,0xF5,0x31,0xE5,0xC1,0x60
329,0x3A,0x85,0x30,0x82,0x85,0x2F,0x83,0xE4,0x93,0xFE,0x05,0x30,0xE5,0x30,0x70,0x02
330,0x05,0x2F,0xF5,0x82,0x85,0x2F,0x83,0xE4,0x93,0x90,0x1B,0x31,0x51,0x70,0x85,0x32
331,0x82,0x85,0x31,0x83,0xE4,0x93,0xFE,0x05,0x32,0xE5,0x32,0x70,0x02,0x05,0x31,0xF5
332,0x82,0x85,0x31,0x83,0xE4,0x93,0x90,0x1B,0x33,0x51,0x70,0x90,0x1B,0x31,0x31,0x79
333,0x90,0x1B,0x33,0x31,0x79,0x90,0x1B,0x31,0xE0,0xF5,0x3E,0xA3,0xE0,0xF5,0x3F,0xA3
334,0xE0,0xF5,0x40,0xA3,0xE0,0xF5,0x41,0xE4,0xF5,0x3A,0xF5,0x3B,0x75,0xC1,0x01,0x75
335,0xC2,0x44,0x51,0x79,0xE4,0xF5,0xC1,0x22,0x25,0x30,0xF5,0x30,0xE4,0x35,0x2F,0xF5
336,0x2F,0x22,0x8F,0xFA,0xED,0xF5,0xFB,0xEC,0xF5,0xFC,0x75,0xF8,0x04,0x02,0x08,0x90
337,0xFD,0xED,0xFF,0xEE,0xF0,0xA3,0xEF,0xF0,0x22,0xE4,0xF5,0x33,0xAF,0xC1,0xEF,0xAD
338,0xC2,0xF5,0x3A,0xED,0xF5,0x3B,0xD3,0x94,0x00,0xE5,0x3A,0x94,0x02,0x40,0x09,0x75
339,0x33,0x01,0x75,0x3A,0x02,0x75,0x3B,0x00,0xC3,0xE5,0x3A,0x94,0x00,0x50,0x08,0x75
340,0x33,0x01,0xE4,0xF5,0x3A,0xF5,0x3B,0xAF,0x3B,0xAE,0x3A,0x71,0x6A,0x8E,0x3C,0x8F
341,0x3D,0x53,0xCB,0xF7,0xE5,0x3C,0x54,0x1F,0xFC,0xAD,0x3D,0x7F,0x50,0x51,0x62,0x75
342,0x34,0x00,0x75,0x35,0xFA,0x7F,0x05,0x7E,0x00,0x12,0x04,0x31,0x85,0x3C,0x36,0x85
343,0x3D,0x37,0x71,0x3C,0xC3,0x33,0xCE,0x33,0xCE,0xD8,0xF9,0x78,0x03,0xCE,0xA2,0xE7
344,0x13,0xCE,0x13,0xD8,0xF8,0xFF,0xC3,0xE5,0x37,0x9F,0xF5,0x37,0xE5,0x36,0x9E,0xF5
345,0x36,0xC3,0x64,0x80,0x94,0x80,0x50,0x0F,0xAE,0x36,0xAF,0x37,0x7C,0xFF,0x7D,0xFF
346,0x12,0x00,0x5E,0x8E,0x36,0x8F,0x37,0xE5,0x35,0x15,0x35,0x70,0x02,0x15,0x34,0xC3
347,0xE5,0x37,0x94,0x14,0xE5,0x36,0x64,0x80,0x94,0x80,0x40,0x06,0xE5,0x35,0x45,0x34
348,0x70,0xA3,0xE5,0x35,0x45,0x34,0x70,0x03,0x75,0x33,0x04,0x71,0x55,0xE4,0xF5,0xC1
349,0x85,0x33,0xC2,0xE5,0x34,0xF5,0xC3,0xE5,0x35,0xF5,0xC4,0x22,0x7F,0x5A,0x71,0x44
350,0xEF,0x78,0x03,0x22,0x8F,0xFA,0x75,0xF8,0x06,0x12,0x08,0x90,0xAF,0xFC,0xEF,0xFE
351,0xAD,0xFB,0xED,0xFF,0x22,0xE5,0x3C,0x54,0x1F,0xFE,0xE4,0x25,0x3D,0xFD,0xEE,0x34
352,0x20,0xFC,0x7F,0x50,0x51,0x62,0x43,0xCB,0x08,0x22,0x8E,0x38,0x8F,0x39,0x71,0xFB
353,0x78,0x02,0x71,0xF2,0x12,0x0F,0x35,0xAE,0x38,0xAF,0x39,0xE4,0xFC,0xFD,0x12,0x01
354,0x74,0x78,0x09,0x12,0x02,0xA2,0xAD,0x07,0xAC,0x06,0xE5,0x41,0xAE,0x40,0x78,0x02
355,0xC3,0x33,0xCE,0x33,0xCE,0xD8,0xF9,0xC3,0x9D,0xFF,0xEE,0x9C,0xFE,0xEF,0x78,0x02
356,0xCE,0xA2,0xE7,0x13,0xCE,0x13,0xD8,0xF8,0xFF,0x22,0xD3,0xEF,0x95,0x41,0xE5,0x40
357,0x64,0x80,0xF8,0xEE,0x64,0x80,0x98,0x40,0x04,0xE4,0xFE,0xFF,0x22,0xC3,0xEF,0x95
358,0x3F,0xE5,0x3E,0x64,0x80,0xF8,0xEE,0x64,0x80,0x98,0x50,0x05,0x7E,0x02,0x7F,0x00
359,0x22,0xC3,0xE5,0x41,0x9F,0xFF,0xE5,0x40,0x9E,0x78,0x09,0x71,0xF2,0xC0,0x06,0xC0
360,0x07,0x71,0xFB,0xAB,0x07,0xFA,0x33,0x95,0xE0,0xF9,0xF8,0xD0,0x07,0xD0,0x06,0x02
361,0x01,0xFF,0xFE,0x33,0x95,0xE0,0xFD,0xFC,0x02,0x02,0xB5,0xC3,0xE5,0x41,0x95,0x3F
362,0xFF,0xE5,0x40,0x95,0x3E,0x22,0x91,0x55,0x4E,0x70,0x05,0x75,0xC1,0x01,0x80,0x05
363,0x90,0x1B,0x45,0x91,0x21,0x11,0x95,0xF5,0xC2,0xED,0xF5,0xC3,0xA3,0xE0,0xF5,0xC4
364,0x22,0xEE,0xF0,0xA3,0xEF,0xF0,0x12,0x0E,0x2F,0xE4,0xF5,0xC1,0x22,0x91,0x55,0xD3
365,0x94,0x80,0xEE,0x94,0x0C,0x50,0x09,0xC3,0xEF,0x94,0x32,0xEE,0x94,0x00,0x50,0x05
366,0x75,0xC1,0x01,0x80,0x05,0x90,0x1B,0x47,0x91,0x21,0x90,0x1B,0x14,0x11,0x98,0xF5
367,0xC2,0xED,0xF5,0xC3,0x22,0xAF,0xC1,0xEF,0xFF,0xAD,0xC2,0xED,0x90,0x1B,0x49,0xCF
368,0xF0,0xA3,0xEF,0xF0,0x90,0x1B,0x49,0xE0,0xFE,0xA3,0xE0,0xFF,0x22,0x91,0x55,0xC3
369,0x94,0xFF,0xEE,0x94,0x5F,0x50,0x0A,0xAD,0xC4,0x12,0x09,0x43,0xE4,0xF5,0xC1,0x80
370,0x03,0x75,0xC1,0x01,0xE4,0xF5,0xC2,0x22,0x90,0x1B,0x49,0xE5,0xC2,0xF0,0xE4,0xA3
371,0xF0,0x90,0x1B,0x49,0xE0,0xFF,0xC3,0x94,0xFF,0x50,0x0C,0x31,0x2B,0x90,0x1B,0x4A
372,0xEF,0xF0,0xE4,0xF5,0xC1,0x80,0x03,0x75,0xC1,0x01,0xE4,0xF5,0xC2,0xF5,0xC3,0x90
373,0x1B,0x4A,0xE0,0xF5,0xC4,0x22,0xAF,0xC1,0xEF,0xFF,0xAD,0xC2,0xED,0x90,0x1B,0x49
374,0xCF,0xF0,0xA3,0xEF,0xF0,0xE4,0xA3,0x91,0x63,0xC3,0x94,0xFF,0xEE,0x94,0x5F,0x50
375,0x0D,0x12,0x0D,0x3A,0x90,0x1B,0x4B,0xEF,0xF0,0xE4,0xF5,0xC1,0x80,0x03,0x75,0xC1
376,0x01,0xE4,0xF5,0xC2,0xF5,0xC3,0x90,0x1B,0x4B,0xE0,0xF5,0xC4,0x22,0xE4,0xFF,0xE5
377,0xC1,0xC3,0x94,0xC1,0x50,0x0A,0xAF,0xC1,0x12,0x0D,0x22,0xE4,0xF5,0xC1,0x80,0x03
378,0x75,0xC1,0x01,0x8F,0xC4,0xE4,0xF5,0xC3,0xF5,0xC2,0x22,0x8F,0x2F,0xAB,0x2F,0xAD
379,0xC3,0xAF,0xC2,0xB1,0x27,0x8F,0xC3,0x05,0xC2,0xAB,0x2F,0xAD,0xC4,0xAF,0xC2,0xB1
380,0x27,0x8F,0xC4,0xE4,0xF5,0xC1,0x22,0x8D,0x37,0xAE,0x03,0xEF,0x7C,0x00,0x7B,0x01
381,0x24,0x23,0xF9,0xEC,0x34,0x1B,0xFA,0x90,0x1B,0x50,0x12,0x03,0x0C,0xEE,0x60,0x11
382,0xEF,0xC3,0x94,0x26,0x50,0x0B,0x90,0x1B,0x50,0x12,0x02,0xEC,0xE5,0x37,0x12,0x00
383,0x4C,0x90,0x1B,0x50,0x12,0x0F,0xE3,0xFF,0x22,0xE4,0xFF,0x80,0xAE,0x7F,0x01,0x80
384,0xAA,0xAD,0x3B,0xAC,0x3A,0xE4,0xF5,0xC1,0x8C,0xC3,0xAF,0x05,0xEF,0xF5,0xC4,0x22
385,0xAF,0xC2,0x7E,0x00,0xEF,0x78,0x10,0xC3,0x33,0xCE,0x33,0xCE,0xD8,0xF9,0xFD,0xAC
386,0x06,0xAF,0xC1,0x7E,0x00,0xEF,0x78,0x18,0xC3,0x33,0xCE,0x33,0xCE,0xD8,0xF9,0xB1
387,0xAA,0xAF,0xC3,0xEF,0x4C,0xFE,0xED,0xFF,0xAD,0xC4,0xEF,0x4D,0xFF,0xE4,0xFC,0xFD
388,0x90,0x1B,0x60,0x12,0x02,0xE0,0xE4,0xF5,0xC1,0x22,0xFF,0xEE,0x4C,0xFC,0xEF,0x4D
389,0xFD,0x22,0x8E,0x2F,0x8F,0x30,0xC3,0xE5,0x30,0x94,0x64,0xE5,0x2F,0x94,0x00,0x50
390,0x0C,0xF1,0x20,0xC2,0x44,0xF1,0x17,0x7E,0x40,0x7D,0x06,0x80,0x6D,0xC3,0xE5,0x30
391,0x94,0xC8,0xE5,0x2F,0x94,0x00,0x50,0x0A,0xF1,0x20,0xF1,0x11,0x7E,0x80,0x7D,0x0C
392,0x80,0x58,0xC3,0xE5,0x30,0x94,0x90,0xE5,0x2F,0x94,0x01,0x50,0x0F,0xC2,0x40,0xD2
393,0x41,0xC2,0x42,0xC2,0x43,0xF1,0x11,0xFE,0x7D,0x19,0x80,0x3E,0xC3,0xE5,0x30,0x94
394,0x20,0xE5,0x2F,0x94,0x03,0x50,0x0D,0xD2,0x40,0xC2,0x41,0xC2,0x42,0xF1,0x0F,0xFE
395,0x7D,0x32,0x80,0x26,0xC3,0xE5,0x30,0x94,0x40,0xE5,0x2F,0x94,0x06,0x50,0x09,0xC2
396,0x40,0xF1,0x0B,0xFE,0x7D,0x64,0x80,0x12,0xC3,0xE5,0x30,0x94,0x80,0xE5,0x2F,0x94
397,0x0C,0x50,0x0F,0xD2,0x40,0xF1,0x0B,0xFE,0x7D,0xC8,0xFC,0x12,0x01,0xFF,0x8E,0x31
398,0x8F,0x32,0xC3,0xE4,0x95,0x32,0xF5,0x34,0x74,0x20,0x95,0x31,0xF5,0x33,0xA2,0x41
399,0xE4,0x33,0x24,0x01,0xFB,0xE4,0x33,0xFA,0xE4,0x33,0xF9,0xE4,0x33,0xF8,0xA2,0x40
400,0x12,0x0F,0x24,0xA2,0x42,0x12,0x0F,0x24,0xA2,0x43,0x12,0x0F,0x24,0xA2,0x44,0xE4
401,0x33,0x24,0x01,0xFF,0xE4,0x33,0xFE,0xE4,0x33,0xFD,0xE4,0x33,0xFC,0x12,0x01,0x74
402,0xC0,0x04,0x12,0x0F,0x37,0xE5,0x33,0xFF,0xC3,0x74,0x20,0x9F,0xFD,0xE4,0x94,0x00
403,0xFC,0x7E,0x06,0x7F,0x40,0x12,0x00,0x70,0xE4,0xFC,0xFD,0xD0,0x00,0x12,0x01,0x74
404,0x90,0x1B,0x14,0xEE,0xF0,0xA3,0xEF,0xF0,0xA2,0x41,0xE4,0xFE,0x33,0x54,0x01,0x78
405,0x07,0xC3,0x33,0xCE,0x33,0xCE,0xD8,0xF9,0xFD,0xAC,0x06,0xA2,0x40,0xE4,0x33,0x54
406,0x01,0x4C,0xFC,0xA2,0x42,0xE4,0xFE,0x33,0x54,0x01,0x78,0x06,0xC3,0x33,0xCE,0x33
407,0xCE,0xD8,0xF9,0xB1,0xAA,0xA2,0x43,0xE4,0xFE,0x33,0x54,0x01,0x78,0x05,0xC3,0x33
408,0xCE,0x33,0xCE,0xD8,0xF9,0xB1,0xAA,0xA2,0x44,0xE4,0x33,0x54,0x01,0xC4,0xF8,0x54
409,0x0F,0xC8,0x68,0xFF,0xE4,0xC4,0x54,0xF0,0x48,0x4C,0xFC,0xEF,0x4D,0xFD,0xE5,0x33
410,0x54,0x0F,0xFF,0xEC,0xF5,0x48,0xEF,0x4D,0xF5,0x49,0x22,0xD2,0x41,0xD2,0x42,0xD2
411,0x43,0xD2,0x44,0xAE,0x2F,0xAF,0x30,0xAB,0x07,0xAA,0x06,0xE4,0xF9,0xF8,0xFF,0x22
412,0xC2,0x40,0xC2,0x41,0xC2,0x42,0xC2,0x43,0x22,0xE4,0xF5,0xC1,0xF1,0x31,0x8F,0xC2
413,0x22,0x7F,0x20,0x12,0x0D,0x22,0xEF,0x54,0x03,0x64,0x03,0x7F,0x00,0x60,0x02,0x7F
414,0x01,0x22,0xAF,0xC1,0xEF,0x14,0x60,0x0C,0x04,0x70,0x16,0x74,0xFF,0x90,0x1B,0x3B
415,0xF0,0xA3,0x80,0x08,0x90,0x1B,0x3B,0xE4,0xF0,0xA3,0x74,0x0A,0xF0,0xE4,0xF5,0xC1
416,0x22,0x75,0xC1,0x01,0x22,0xAF,0xC1,0xEF,0xFE,0xAD,0xC2,0xED,0xFF,0xE4,0xF5,0xC1
417,0x8F,0x82,0x8E,0x83,0x93,0xFC,0x74,0x01,0x93,0xF5,0xC3,0xEC,0xF5,0xC4,0x22,0xE4
418,0xF5,0x8F,0xF1,0x92,0x75,0xA8,0x81,0x53,0xC9,0xFE,0x75,0xC5,0xFF,0x12,0x04,0x6F
419,0x80,0xFB,0x75,0xC9,0xFF,0x75,0xCA,0xFF,0x75,0xC7,0xFF,0x75,0xC8,0xFF,0x22,0xE5
420,0xC1,0xB4,0x80,0x05,0x12,0x09,0x2E,0x80,0x3E,0xE4,0xFD,0xAF,0xC1,0x12,0x18,0x35
421,0x12,0x19,0xB7,0x70,0x06,0xE9,0xF4,0x70,0x02,0xEA,0xF4,0x70,0x04,0x75,0xC1,0x01
422,0x22,0x90,0x1B,0x0F,0xE0,0x60,0x03,0x12,0x0F,0x87,0xE4,0x90,0x1B,0x0F,0xF0,0xA3
423,0xE5,0xC1,0xF0,0xC2,0x48,0xC2,0x47,0x12,0x0A,0xDE,0x12,0x0F,0xAA,0x7F,0x03,0x7E
424,0x00,0x12,0x04,0x31,0x12,0x0E,0x2F,0xE4,0xF5,0xC1,0x22,0xAD,0xC2,0xAF,0xC3,0x12
425,0x18,0x35,0x12,0x19,0xB7,0x70,0x06,0xE9,0xF4,0x70,0x02,0xEA,0xF4,0x70,0x08,0x75
426,0xC1,0x01,0xF5,0xC2,0xF5,0xC3,0x22,0xE5,0xC1,0x90,0x1B,0x4A,0x70,0x05,0x75,0xF0
427,0x9D,0x80,0x04,0xE4,0x75,0xF0,0x9F,0x12,0x00,0xFB,0x90,0x1B,0x49,0xE4,0x75,0xF0
428,0x01,0x12,0x02,0xF5,0x12,0x00,0x06,0xF5,0xC2,0x90,0x1B,0x49,0x12,0x0F,0xE3,0xF5
429,0xC3,0xE4,0xF5,0xC1,0x22,0xAC,0x07,0x90,0x1B,0x2D,0x11,0x70,0x12,0x01,0x11,0xFF
430,0xAE,0xF0,0xF4,0x70,0x02,0xEE,0xF4,0x60,0x1D,0xED,0x70,0x04,0xEF,0x6C,0x60,0x16
431,0xBD,0x01,0x0A,0x12,0x01,0x11,0xE5,0xF0,0xB5,0x04,0x02,0x80,0x09,0x74,0x04,0x29
432,0xF9,0xE4,0x3A,0xFA,0x80,0xD6,0x90,0x00,0x02,0x12,0x01,0x3C,0xFF,0xAE,0xF0,0x22
433,0xE0,0xFE,0xA3,0xE0,0xAA,0x06,0xF9,0x7B,0xFF,0x22,0xEF,0x24,0x34,0x60,0x06,0x04
434,0x70,0x05,0x8D,0xCB,0x22,0x8D,0xCC,0x22,0x8F,0xFA,0x8D,0xFB,0x75,0xF8,0x20,0x02
435,0x08,0x90,0x90,0x1B,0x49,0xE5,0xC2,0xF0,0xE0,0xFF,0xC3,0x94,0xFF,0x50,0x09,0xAD
436,0xC4,0x11,0x88,0xE4,0xF5,0xC1,0x80,0x03,0x75,0xC1,0x01,0xE4,0xF5,0xC2,0x22,0xE4
437,0xFD,0xAF,0xC1,0xEF,0x14,0x60,0x25,0x14,0x60,0x39,0x24,0xFC,0x60,0x51,0x14,0x60
438,0x56,0x14,0x60,0x5B,0x24,0x08,0x70,0x63,0xE5,0xC2,0xD3,0x94,0x01,0x40,0x04,0x7D
439,0x01,0x80,0x5A,0xAF,0xC2,0x90,0x1B,0x00,0xEF,0xF0,0x80,0x51,0xAF,0xC3,0xAC,0xC2
440,0xEC,0x2F,0xFF,0xE4,0x33,0x4F,0x70,0x04,0x7D,0x01,0x80,0x41,0x31,0x30,0x90,0x1B
441,0x01,0x80,0x29,0x31,0x30,0xD3,0x94,0x80,0xEE,0x94,0x0C,0x50,0x09,0xC3,0xEF,0x94
442,0x32,0xEE,0x94,0x00,0x50,0x04,0x7D,0x01,0x80,0x23,0x90,0x1B,0x03,0x80,0x0D,0x90
443,0x1B,0x09,0xE5,0xC2,0xF0,0x80,0x16,0x31,0x30,0x90,0x1B,0x37,0xEE,0x80,0x06,0xAF
444,0xC2,0x90,0x1B,0x39,0xE4,0xF0,0xA3,0xEF,0xF0,0x80,0x02,0x7D,0x01,0x8D,0xC1,0x22
445,0xAF,0xC2,0xEF,0xFE,0xAC,0xC3,0xEC,0xFB,0xEB,0xFF,0x22,0x90,0x1B,0x00,0xE0,0x60
446,0x04,0xD2,0x47,0x80,0x02,0xC2,0x47,0x30,0x47,0x15,0x12,0x0F,0xBB,0x90,0x1B,0x02
447,0xE0,0x9F,0x90,0x1B,0x01,0xE0,0x9E,0x40,0x03,0xD2,0x48,0x22,0xC2,0x48,0x22,0x12
448,0x0F,0xBB,0x90,0x1B,0x46,0xE0,0x9F,0x90,0x1B,0x45,0xE0,0x9E,0x40,0x03,0xD2,0x48
449,0x22,0xC2,0x48,0x22,0xC0,0xE0,0xC0,0xF0,0xC0,0x83,0xC0,0x82,0xC0,0xD0,0x75,0xD0
450,0x00,0xC0,0x00,0xC0,0x01,0xC0,0x02,0xC0,0x03,0xC0,0x04,0xC0,0x05,0xC0,0x06,0xC0
451,0x07,0xE5,0xC7,0x30,0xE0,0x06,0x12,0x08,0x30,0x53,0xC7,0x01,0xD0,0x07,0xD0,0x06
452,0xD0,0x05,0xD0,0x04,0xD0,0x03,0xD0,0x02,0xD0,0x01,0xD0,0x00,0xD0,0xD0,0xD0,0x82
453,0xD0,0x83,0xD0,0xF0,0xD0,0xE0,0x32,0xAA,0x06,0xA9,0x07,0x7B,0xFF,0x90,0x1B,0x49
454,0x12,0x03,0x0C,0x90,0x1B,0x49,0x12,0x02,0xEC,0x74,0xFF,0xF5,0x83,0xF5,0x82,0x6B
455,0x22,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
456,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
457,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
458,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
459,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
460,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
461,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
462,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
463,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
464,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
465,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
466,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
467,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
468,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
469,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
470,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
471,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
472,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
473,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
474,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
475,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
476,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
477,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
478,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
479,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
480,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
481,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
482,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
483,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
484,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
485,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
486,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
487,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
488,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
489,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
490,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
491,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
492,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
493,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
494,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
495,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
496,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
497,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
498,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
499,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
500,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
501,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
502,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
503,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
504,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
505,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
506,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
507,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
508,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
509,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
510,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
511,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
512,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
513,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
514,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
515,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
516,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
517,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
518,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
519,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
520,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
521,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
522,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
523,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
524,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
525,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
526,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
527,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
528,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
529,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
530,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
531,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
532,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
533,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
534,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
535,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
536,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
537,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
538,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
539,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
540,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
541,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
542,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
543,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF
544,0x21,0x20,0x24,0x90,0x21,0xB2,0x21,0x95,0x21,0x94,0x60,0x00,0x64,0x21,0x95,0x26
545,0x5E,0x25,0x66,0x2A,0x22,0x21,0x2E,0x26,0x30,0x22,0x38,0x24,0x40,0x23,0x9E,0x22
546,0x9A,0x84,0x0E,0x84,0xEE,0x84,0xEE,0x22,0x52,0x21,0x20,0x21,0x58,0xFF,0xFF,0xFF
547,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x40,0x03,0x00,0x01
548,0x03,0x02,0x01,0x00,0xFF,0x60,0x03,0x18,0x00,0xE1,0x0F,0xF8,0xF4,0xF8,0x28,0x24
549,0x0C,0x26,0x00,0x27,0x0F,0x00,0x0E,0x02,0x01,0xD0,0x07,0x64,0x00,0x94,0x11,0xE8
550,0x03,0x64,0x00,0xF4,0x01,0x02,0x11,0x00,0xE8,0x03,0xFC,0x18,0x03,0xE9,0xFF,0xFF
551,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x60,0x03,0x07,0x06,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
552,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
553,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
554};
555
556struct ov14810_reg {
557 u16 addr;
558 u16 val;
559};
560
561struct ov14810_sensor {
562 struct i2c_client *i2c_client;
563 struct ov14810_platform_data *pdata;
564};
565
566struct ov14810_info {
567 int mode;
568 int uC_programmed;
569 struct ov14810_sensor sensor;
570 struct ov14810_sensor uC;
571 struct ov14810_sensor slaveDev;
572};
573
574static struct ov14810_info *info;
575
576#define OV14810_TABLE_WAIT_MS 0
577#define OV14810_TABLE_END 1
578
579static struct ov14810_reg mode_4416x3312[] = {
580 {0x0103, 0x01},
581
582 {0x3003, 0x09},
583 {0x3004, 0x00},
584 {0x3005, 0xa7},
585 {0x3006, 0x80},
586 {0x3007, 0x08},
587 {0x3013, 0x1f},
588
589 {0x3018, 0x04},
590 {0x301b, 0xe0},
591 {0x301c, 0xf8},
592 {0x3020, 0x01},
593 {0x3106, 0x05},
594 {0x3600, 0x2d},
595 {0x3601, 0x1f},
596 {0x360a, 0x2e},
597 {0x360f, 0x24},
598 {0x3611, 0x6c},
599 {0x3613, 0x84},
600 {0x3705, 0xd1},
601 {0x3707, 0x73},
602 {0x3708, 0x01},
603 {0x370e, 0x04},
604 {0x3710, 0x40},
605 {0x3711, 0x1c},
606 {0x3717, 0x80},
607 {0x3718, 0x11},
608 {0x3719, 0x11},
609 {0x371b, 0xa0},
610 {0x371e, 0x2c},
611 {0x3723, 0x30},
612 {0x3726, 0x70},
613 {0x3808, 0x00},
614 {0x380a, 0x00},
615 {0x3817, 0x24},
616 {0x3819, 0x80},
617 {0x3a00, 0x78},
618 {0x3a13, 0x46},
619 {0x3a18, 0x00},
620 {0x3a19, 0x7f},
621 {0x3a1a, 0x06},
622 {0x3a25, 0x83},
623 {0x3b09, 0x0a},
624 {0x4002, 0xc5},
625 {0x4004, 0x02},
626 {0x4005, 0x10},
627 {0x4009, 0x40},
628 {0x404f, 0xff},
629 {0x4709, 0x00},
630 {0x4801, 0x0f},
631 {0x4806, 0x80},
632 {0x4842, 0x01},
633 {0x5000, 0x00},
634 {0x5001, 0x00},
635 {0x5002, 0x00},
636 {0x503b, 0x01},
637 {0x503c, 0x10},
638 {0x5041, 0x0e},
639 {0x5780, 0xfc},
640 {0x5b01, 0x03},
641 {0x5b03, 0x00},
642
643 {0x3003, 0x0a},
644 {0x3005, 0xa7},
645
646 {0x3006, 0x80},
647 {0x3007, 0x08},
648 {0x3013, 0x1f},
649
650 {0x3602, 0x42},
651 {0x3604, 0x80},
652 {0x3605, 0x11},
653 {0x360c, 0x42},
654 {0x360d, 0x13},
655 {0x3614, 0x05},
656
657 {0x3702, 0x10},
658 {0x3704, 0x14},
659 {0x3707, 0x73},
660 {0x370a, 0x80},
661 {0x370b, 0x00},
662 {0x370c, 0x04},
663 {0x370d, 0x0d},
664 {0x370f, 0x61},
665 {0x3713, 0xfa},
666 {0x3714, 0x2f},
667 {0x3715, 0x2c},
668 {0x3716, 0x0b},
669 {0x371c, 0x28},
670 {0x371d, 0x20},
671 {0x3721, 0x08},
672 {0x3724, 0x18},
673 {0x3725, 0x17},
674 {0x3727, 0x65},
675 {0x3728, 0x0c},
676
677 {0x3803, 0x0b},
678 {0x3804, 0x11},
679 {0x3805, 0x40},
680 {0x3806, 0x0c},
681 {0x3807, 0xf9},
682 {0x380c, 0x09},
683 {0x380d, 0x5c},
684 {0x380e, 0x0d},
685 {0x380f, 0x08},
686 {0x3810, 0x44},
687 {0x3811, 0x96},
688 {0x3818, 0x40},
689 {0x381c, 0x30},
690 {0x381d, 0x10},
691 {0x381e, 0x0c},
692 {0x381f, 0xf8},
693 {0x3820, 0x00},
694 {0x3821, 0x0c},
695 {0x3503, 0x13},
696
697 {0x4050, 0xc0},
698 {0x4051, 0x00},
699 {0x4053, 0xa1},
700 {0x4837, 0x1b},
701 {0x503d, 0x00},
702 {0x5042, 0x21},
703 {0x5047, 0x00},
704
705 {0x3a08, 0x1f},
706 {0x3a09, 0x40},
707 {0x3a0a, 0x1a},
708 {0x3a0b, 0x00},
709 {0x3a0d, 0x08},
710 {0x3a0e, 0x06},
711
712 {0x503d, 0x00},
713
714 {0x0100, 0x01},
715 {OV14810_TABLE_END, 0x0000}
716};
717
718static struct ov14810_reg mode_1280x720[] = {
719 {0x0103, 0x01},
720 {OV14810_TABLE_WAIT_MS, 20},
721
722 {0x3003, 0x0a},
723 {0x3004, 0x00},
724 {0x3005, 0xa7},
725 {0x3006, 0x80},
726 {0x3007, 0x08},
727
728 {0x3018, 0x04},
729 {0x301b, 0xe0},
730 {0x301c, 0xf8},
731 {0x3020, 0x01},
732 {0x3106, 0x05},
733 {0x3600, 0x2d},
734 {0x3601, 0x1f},
735 {0x3609, 0x00},
736 {0x360a, 0x2e},
737 {0x360f, 0x24},
738 {0x3611, 0x6c},
739 {0x3613, 0x84},
740 {0x3702, 0x20},
741 {0x3704, 0x28},
742 {0x3705, 0xd1},
743 {0x3708, 0x01},
744 {0x370e, 0x04},
745 {0x3710, 0x40},
746 {0x3711, 0x1c},
747 {0x3714, 0x5f},
748 {0x3715, 0x58},
749 {0x3717, 0x80},
750 {0x3718, 0x11},
751 {0x3719, 0x11},
752 {0x371b, 0xa0},
753 {0x371c, 0x46},
754 {0x371d, 0x40},
755 {0x371e, 0x2c},
756 {0x3723, 0x30},
757 {0x3725, 0x2e},
758 {0x3726, 0x70},
759 {0x3808, 0x00},
760 {0x380a, 0x00},
761 {0x3817, 0x24},
762 {0x3819, 0x80},
763 {0x382c, 0x02},
764 {0x382d, 0x01},
765 {0x3a00, 0x78},
766 {0x3a13, 0x46},
767 {0x3a18, 0x00},
768 {0x3a19, 0x7f},
769 {0x3a1a, 0x06},
770 {0x3a25, 0x83},
771 {0x3b09, 0x0a},
772 {0x4002, 0xc5},
773 {0x4004, 0x02},
774 {0x4005, 0x10},
775 {0x4009, 0x40},
776 {0x404f, 0xff},
777 {0x4709, 0x00},
778 {0x4801, 0x0f},
779 {0x4806, 0x80},
780 {0x4842, 0x01},
781 {0x5000, 0x00},
782 {0x5001, 0x00},
783 {0x5002, 0x00},
784 {0x503b, 0x01},
785 {0x503c, 0x10},
786 {0x5041, 0x0e},
787 {0x5780, 0xfc},
788 {0x5b00, 0x10},
789 {0x5b01, 0x5b},
790 {0x5b03, 0x00},
791
792
793 {0x3005, 0xa7},
794 {0x3006, 0x80},
795 {0x3007, 0x08},
796 {0x3013, 0x1f},
797
798 {0x3602, 0x53},
799 {0x3604, 0x80},
800 {0x3605, 0x01},
801 {0x360b, 0x0c},
802 {0x360c, 0x45},
803 {0x360d, 0x03},
804 {0x3614, 0x05},
805
806 {0x3707, 0x73},
807 {0x370a, 0x81},
808 {0x370b, 0x20},
809 {0x370c, 0x04},
810 {0x370d, 0x01},
811 {0x370f, 0x00},
812 {0x3713, 0xe6},
813 {0x3716, 0xf0},
814 {0x3721, 0x08},
815 {0x3724, 0x2e},
816 {0x3727, 0x60},
817 {0x3728, 0x02},
818
819 {0x3803, 0x07},
820 {0x3804, 0x05}, /* width */
821 {0x3805, 0x09},
822 {0x3806, 0x02}, /* height */
823 {0x3807, 0xd8},
824 {0x380c, 0x05},
825 {0x380d, 0x66},
826 {0x380e, 0x02},
827 {0x380f, 0xe4},
828 {0x3810, 0x22},
829 {0x3811, 0x02},
830 {0x3818, 0x45},
831 {0x381c, 0x13},
832 {0x381d, 0xb8},
833 {0x381e, 0x05}, /* height w/o skipping */
834 {0x381f, 0xc0},
835 {0x3820, 0x03},
836 {0x3821, 0xa8},
837 {0x3503, 0x13}, /* Manual exposure, gain control */
838
839 {0x4050, 0xc0},
840 {0x4051, 0x00},
841 {0x4053, 0xa1},
842 {0x4837, 0x1b},
843 {0x503d, 0x00},
844 {0x5042, 0x31},
845 {0x5047, 0x00},
846
847 {0x100, 0x01},
848 {OV14810_TABLE_END, 0x0000}
849};
850
851enum {
852 OV14810_MODE_4416x3312,
853 OV14810_MODE_1280x720
854};
855
856static struct ov14810_reg *mode_table[] = {
857 [OV14810_MODE_4416x3312] = mode_4416x3312,
858 [OV14810_MODE_1280x720] = mode_1280x720
859};
860
861static inline void ov14810_get_frame_length_regs(struct ov14810_reg *regs,
862 u32 frame_length)
863{
864 regs->addr = OV14810_FRAME_LENGTH_REG_ADDR0;
865 regs->val = (frame_length >> 8) & 0xff;
866 (regs + 1)->addr = OV14810_FRAME_LENGTH_REG_ADDR1;
867 (regs + 1)->val = (frame_length) & 0xff;
868}
869
870static inline void ov14810_get_coarse_time_regs(struct ov14810_reg *regs,
871 u32 coarse_time)
872{
873 regs->addr = OV14810_COARSE_TIME_REG_ADDR0;
874 regs->val = (coarse_time >> 12) & 0xff;
875 (regs + 1)->addr = OV14810_COARSE_TIME_REG_ADDR1;
876 (regs + 1)->val = (coarse_time >> 4) & 0xff;
877 (regs + 2)->addr = OV14810_COARSE_TIME_REG_ADDR2;
878 (regs + 2)->val = (coarse_time & 0xf) << 4;
879}
880
881static inline void ov14810_get_gain_reg(struct ov14810_reg *regs, u16 gain)
882{
883 regs->addr = OV14810_GAIN_REG_ADDR0;
884 regs->val = gain;
885}
886
887static int ov14810_write16(struct i2c_client *client, u16 addr, u8 val)
888{
889 int err;
890 struct i2c_msg msg;
891 unsigned char data[3];
892
893 if (!client->adapter)
894 return -ENODEV;
895
896 data[0] = (u8) (addr >> 8);
897 data[1] = (u8) (addr & 0xff);
898 data[2] = (u8) (val & 0xff);
899
900 msg.addr = client->addr;
901 msg.flags = 0;
902 msg.len = 3;
903 msg.buf = data;
904
905 err = i2c_transfer(client->adapter, &msg, 1);
906 if (err != 1) {
907 pr_err("ov14810: i2c transfer failed %x %x\n", addr, val);
908 return -EIO;
909 }
910
911 return 0;
912}
913
914static int ov14810_write8(struct i2c_client *client, u8 addr, u8 val)
915{
916 int err;
917 struct i2c_msg msg;
918 unsigned char data[2];
919
920 if (!client->adapter)
921 return -ENODEV;
922
923 data[0] = (u8) (addr);
924 data[1] = (u8) (val & 0xff);
925
926 msg.addr = client->addr;
927 msg.flags = 0;
928 msg.len = 2;
929 msg.buf = data;
930
931 err = i2c_transfer(client->adapter, &msg, 1);
932 if (err != 1) {
933 pr_err("ov14810: i2c transfer failed %x %x\n",addr, val);
934 return -EIO;
935 }
936
937 return 0;
938}
939
940static int ov14810_write_reg_helper(struct ov14810_info *info,
941 u16 addr, u8 val)
942{
943 return ov14810_write16(info->sensor.i2c_client, addr, val);
944}
945
946static int ov14810_write_table(struct ov14810_info *info,
947 const struct ov14810_reg table[],
948 const struct ov14810_reg override_list[],
949 int num_override_regs)
950{
951 int err;
952 const struct ov14810_reg *next;
953 int i;
954 u16 val;
955
956 for (next = table; next->addr != OV14810_TABLE_END; next++) {
957 val = next->val;
958
959 if (next->addr == OV14810_TABLE_WAIT_MS) {
960 msleep(val);
961 continue;
962 }
963
964 /* When an override list is passed in, replace the reg */
965 /* value to write if the reg is in the list */
966 if (override_list) {
967 for (i = 0; i < num_override_regs; i++) {
968 if (next->addr == override_list[i].addr) {
969 val = override_list[i].val;
970 break;
971 }
972 }
973 }
974 err = ov14810_write_reg_helper(info, next->addr, val);
975 }
976 return err;
977}
978
979static int ov14810_set_mode(struct ov14810_info *info, struct ov14810_mode *mode)
980{
981 int sensor_mode;
982 int err;
983 struct ov14810_reg reg_list[6];
984
985 pr_info("%s: xres %u yres %u framelength %u coarsetime %u gain %u\n",
986 __func__, mode->xres, mode->yres, mode->frame_length,
987 mode->coarse_time, mode->gain);
988 if (mode->xres == 1280 && mode->yres == 720)
989 sensor_mode = OV14810_MODE_1280x720;
990 else if (mode->xres == 4416 && mode->yres == 3312)
991 sensor_mode = OV14810_MODE_4416x3312;
992 else {
993 pr_err("%s: invalid resolution supplied to set mode %d %d\n",
994 __func__, mode->xres, mode->yres);
995 return -EINVAL;
996 }
997
998 /* get a list of override regs for the asking frame length, */
999 /* coarse integration time, and gain. */
1000 ov14810_get_frame_length_regs(reg_list, mode->frame_length);
1001 ov14810_get_coarse_time_regs(reg_list + 2, mode->coarse_time);
1002 ov14810_get_gain_reg(reg_list + 5, mode->gain);
1003
1004 err = ov14810_write_table(info, mode_table[sensor_mode],
1005 reg_list, 6);
1006
1007 if (err)
1008 return err;
1009
1010 info->mode = sensor_mode;
1011 return 0;
1012}
1013
1014static int ov14810_set_frame_length(struct ov14810_info *info, u32 frame_length)
1015{
1016 struct ov14810_reg reg_list[2];
1017 int i;
1018 int ret;
1019
1020 ov14810_get_frame_length_regs(reg_list, frame_length);
1021
1022 for (i = 0; i < 2; i++) {
1023 ret = ov14810_write_reg_helper(info, reg_list[i].addr,
1024 reg_list[i].val);
1025 if (ret)
1026 return ret;
1027 }
1028
1029 return 0;
1030}
1031
1032static int ov14810_set_coarse_time(struct ov14810_info *info, u32 coarse_time)
1033{
1034 int ret;
1035
1036 struct ov14810_reg reg_list[3];
1037 int i;
1038
1039 ov14810_get_coarse_time_regs(reg_list, coarse_time);
1040
1041 ret = ov14810_write_reg_helper(info, OV14810_GROUP_ACCESS_REG_ADDR, 0x01);
1042 if (ret)
1043 return ret;
1044
1045 for (i = 0; i < 3; i++) {
1046 ret = ov14810_write_reg_helper(info, reg_list[i].addr,
1047 reg_list[i].val);
1048 if (ret)
1049 return ret;
1050 }
1051
1052 ret = ov14810_write_reg_helper(info, OV14810_GROUP_ACCESS_REG_ADDR, 0x11);
1053 if (ret)
1054 return ret;
1055
1056 ret = ov14810_write_reg_helper(info, OV14810_GROUP_ACCESS_REG_ADDR, 0xa1);
1057 if (ret)
1058 return ret;
1059
1060 return 0;
1061}
1062
1063static int ov14810_set_gain(struct ov14810_info *info, u16 gain)
1064{
1065 int ret;
1066 struct ov14810_reg reg_list;
1067
1068 ov14810_get_gain_reg(&reg_list, gain);
1069
1070 ret = ov14810_write_reg_helper(info, reg_list.addr, reg_list.val);
1071
1072 return ret;
1073}
1074
1075static int ov14810_set_power(int powerLevel)
1076{
1077 pr_info("%s: powerLevel=%d \n", __func__, powerLevel);
1078
1079 if (info->sensor.pdata) {
1080 if (powerLevel && info->sensor.pdata->power_on) {
1081 info->sensor.pdata->power_on();
1082 msleep(1000);
1083 }
1084 else if (info->sensor.pdata->power_off) {
1085 info->sensor.pdata->power_off();
1086 }
1087 }
1088
1089 return 0;
1090}
1091
1092static long ov14810_ioctl(struct file *file,
1093 unsigned int cmd, unsigned long arg)
1094{
1095 struct ov14810_info *info = file->private_data;
1096 int err;
1097
1098 switch (cmd) {
1099 case OV14810_IOCTL_SET_MODE:
1100 {
1101 struct ov14810_mode mode;
1102
1103 err = copy_from_user(&mode,(const void __user *)arg,
1104 sizeof(struct ov14810_mode));
1105 if (err) {
1106 pr_err("%s %d\n", __func__, __LINE__);
1107 return err;
1108 }
1109
1110 return ov14810_set_mode(info, &mode);
1111 }
1112 case OV14810_IOCTL_SET_FRAME_LENGTH:
1113 return ov14810_set_frame_length(info, (u32)arg);
1114 case OV14810_IOCTL_SET_COARSE_TIME:
1115 return ov14810_set_coarse_time(info, (u32)arg);
1116 case OV14810_IOCTL_SET_GAIN:
1117 return ov14810_set_gain(info, (u16)arg);
1118 case OV14810_IOCTL_GET_STATUS:
1119 {
1120 u16 status = 0;
1121 err = copy_to_user((void __user *)arg, &status,2);
1122 if (err) {
1123 pr_err("%s %d\n", __func__, __LINE__);
1124 return err;
1125 }
1126 return 0;
1127 }
1128 default:
1129 return -EINVAL;
1130 }
1131 return 0;
1132}
1133
1134static int ov14810_slavedev_open(void)
1135{
1136 pr_info("%s\n", __func__);
1137
1138 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0x19, 0x67);
1139 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0x18, 0x02);
1140
1141 return 0;
1142}
1143
1144static int ov14810_slavedev_reset(void)
1145{
1146 pr_info("%s\n", __func__);
1147
1148 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0x18, 0x03);
1149 msleep(1000);
1150
1151 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0xc1, 0x0);
1152 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0xc2, 0x0);
1153 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0xc3, 0x0);
1154 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0xc4, 0x0);
1155 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0xc5, 0x0);
1156
1157 msleep(1000);
1158
1159 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0xc1, 0x0);
1160 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0xc2, 0x0);
1161 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0xc3, 0x0);
1162 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0xc4, 0x0);
1163 OV14810_I2C_WRITE8(info->slaveDev.i2c_client, 0xc5, 0x17);
1164
1165 msleep(1000);
1166
1167 return 0;
1168}
1169
1170static int ov14810uC_open(void)
1171{
1172 int i;
1173 int err;
1174
1175 pr_info("ov14810uC programmming started \n");
1176
1177 for (i = 0; i < sizeof(uCProgram); i++) {
1178 ov14810_write16(info->uC.i2c_client,
1179 ( ( (i & 0xff) << 8) | ( (i & 0xff00) >> 8) ), uCProgram[i]);
1180 }
1181 pr_info("ov14810uC programmming finished \n");
1182
1183 err = ov14810_slavedev_reset();
1184
1185 return err;
1186}
1187
1188static int ov14810_open(struct inode *inode, struct file *file)
1189{
1190 int err;
1191 pr_info("%s\n", __func__);
1192 file->private_data = info;
1193
1194 err = ov14810_set_power(1);
1195
1196 if (err)
1197 return err;
1198
1199 if (info->uC_programmed == 0) {
1200 err = ov14810_slavedev_open();
1201
1202 if (err)
1203 return err;
1204
1205 err = ov14810uC_open();
1206 if (!err)
1207 info->uC_programmed = 1;
1208 }
1209
1210 return err;
1211}
1212
1213int ov14810_release(struct inode *inode, struct file *file)
1214{
1215 pr_info("%s\n", __func__);
1216 ov14810_set_power(0);
1217 file->private_data = NULL;
1218 return 0;
1219}
1220
1221static const struct file_operations ov14810_fileops = {
1222 .owner = THIS_MODULE,
1223 .open = ov14810_open,
1224 .unlocked_ioctl = ov14810_ioctl,
1225 .release = ov14810_release,
1226};
1227
1228static struct miscdevice ov14810_device = {
1229 .minor = MISC_DYNAMIC_MINOR,
1230 .name = "ov14810",
1231 .fops = &ov14810_fileops,
1232};
1233
1234static int ov14810_probe(struct i2c_client *client,
1235 const struct i2c_device_id *id)
1236{
1237 int err;
1238 pr_info("%s: probing sensor.\n", __func__);
1239
1240 if (!info) {
1241 info = kzalloc(sizeof(struct ov14810_info), GFP_KERNEL);
1242 if (!info) {
1243 pr_err("ov14810: Unable to allocate memory!\n");
1244 return -ENOMEM;
1245 }
1246 }
1247
1248 err = misc_register(&ov14810_device);
1249 if (err) {
1250 pr_err("ov14810: Unable to register misc device!\n");
1251 kfree(info);
1252 return err;
1253 }
1254
1255 info->sensor.pdata = client->dev.platform_data;
1256 info->sensor.i2c_client = client;
1257
1258 return 0;
1259}
1260
1261static int ov14810_remove(struct i2c_client *client)
1262{
1263 misc_deregister(&ov14810_device);
1264 kfree(info);
1265 return 0;
1266}
1267
1268static int ov14810_uC_probe(struct i2c_client *client,
1269 const struct i2c_device_id *id)
1270{
1271 if (!info) {
1272 info = kzalloc(sizeof(struct ov14810_sensor), GFP_KERNEL);
1273 if (!info) {
1274 pr_err("ov14810uC: Unable to allocate memory!\n");
1275 return -ENOMEM;
1276 }
1277 }
1278 info->uC.pdata = client->dev.platform_data;
1279 info->uC.i2c_client = client;
1280
1281 return 0;
1282}
1283
1284static int ov14810_uC_remove(struct i2c_client *client)
1285{
1286 return 0;
1287}
1288
1289static int ov14810_slavedev_probe(struct i2c_client *client,
1290 const struct i2c_device_id *id)
1291{
1292 pr_info("%s: probing slave Dev of sensor.\n", __func__);
1293
1294 if (!info) {
1295 info = kzalloc(sizeof(struct ov14810_sensor), GFP_KERNEL);
1296 if (!info) {
1297 pr_err("ov14810uC: Unable to allocate memory!\n");
1298 return -ENOMEM;
1299 }
1300 }
1301
1302 info->slaveDev.pdata = client->dev.platform_data;
1303 info->slaveDev.i2c_client = client;
1304 info->uC_programmed = 0;
1305
1306 return 0;
1307}
1308
1309static int ov14810_slavedev_remove(struct i2c_client *client)
1310{
1311 return 0;
1312}
1313
1314static const struct i2c_device_id ov14810_id[] = {
1315 { "ov14810", 0 },
1316 { },
1317};
1318
1319MODULE_DEVICE_TABLE(i2c, ov14810_id);
1320
1321static struct i2c_driver ov14810_i2c_driver = {
1322 .driver = {
1323 .name = "ov14810",
1324 .owner = THIS_MODULE,
1325 },
1326 .probe = ov14810_probe,
1327 .remove = ov14810_remove,
1328 .id_table = ov14810_id,
1329};
1330
1331
1332static const struct i2c_device_id ov14810_uC_id[] = {
1333 { "ov14810uC", 0 },
1334 { },
1335};
1336
1337MODULE_DEVICE_TABLE(i2c, ov14810_uC_id);
1338
1339static struct i2c_driver ov14810_uC_i2c_driver = {
1340 .driver = {
1341 .name = "ov14810uC",
1342 .owner = THIS_MODULE,
1343 },
1344 .probe = ov14810_uC_probe,
1345 .remove = ov14810_uC_remove,
1346 .id_table = ov14810_uC_id,
1347};
1348
1349static const struct i2c_device_id ov14810_slavedev_id[] = {
1350 { "ov14810SlaveDev", 0 },
1351 { },
1352};
1353
1354MODULE_DEVICE_TABLE(i2c, ov14810_slavedev_id);
1355
1356static struct i2c_driver ov14810_slavedev_i2c_driver = {
1357 .driver = {
1358 .name = "ov14810SlaveDev",
1359 .owner = THIS_MODULE,
1360 },
1361 .probe = ov14810_slavedev_probe,
1362 .remove = ov14810_slavedev_remove,
1363 .id_table = ov14810_slavedev_id,
1364};
1365
1366static int __init ov14810_init(void)
1367{
1368 int ret;
1369 pr_info("ov14810 sensor driver loading\n");
1370 ret = i2c_add_driver(&ov14810_i2c_driver);
1371 if (ret)
1372 return ret;
1373
1374 ret = i2c_add_driver(&ov14810_uC_i2c_driver);
1375 if (ret)
1376 return ret;
1377
1378 return i2c_add_driver(&ov14810_slavedev_i2c_driver);
1379}
1380
1381static void __exit ov14810_exit(void)
1382{
1383 i2c_del_driver(&ov14810_slavedev_i2c_driver);
1384 i2c_del_driver(&ov14810_uC_i2c_driver);
1385 i2c_del_driver(&ov14810_i2c_driver);
1386}
1387
1388module_init(ov14810_init);
1389module_exit(ov14810_exit);
1390
diff --git a/drivers/media/video/tegra/ov2710.c b/drivers/media/video/tegra/ov2710.c
new file mode 100644
index 00000000000..a2e02369d8e
--- /dev/null
+++ b/drivers/media/video/tegra/ov2710.c
@@ -0,0 +1,690 @@
1/*
2 * ov2710.c - ov2710 sensor driver
3 *
4 * Copyright (c) 2011, NVIDIA, All Rights Reserved.
5 *
6 * Contributors:
7 * erik lilliebjerg <elilliebjerg@nvidia.com>
8 *
9 * Leverage OV5650.c
10 *
11 * This file is licensed under the terms of the GNU General Public License
12 * version 2. This program is licensed "as is" without any warranty of any
13 * kind, whether express or implied.
14 */
15
16#include <linux/delay.h>
17#include <linux/fs.h>
18#include <linux/i2c.h>
19#include <linux/miscdevice.h>
20#include <linux/slab.h>
21#include <linux/uaccess.h>
22#include <media/ov2710.h>
23
24struct ov2710_reg {
25 u16 addr;
26 u16 val;
27};
28
29struct ov2710_info {
30 int mode;
31 struct i2c_client *i2c_client;
32 struct ov2710_platform_data *pdata;
33};
34
35#define OV2710_TABLE_WAIT_MS 0
36#define OV2710_TABLE_END 1
37#define OV2710_MAX_RETRIES 3
38
39static struct ov2710_reg mode_1920x1080[] = {
40 {0x3103, 0x93},
41 {0x3008, 0x82},
42 {OV2710_TABLE_WAIT_MS, 5},
43 {0x3008, 0x42},
44 {OV2710_TABLE_WAIT_MS, 5},
45 {0x3017, 0x7f},
46 {0x3018, 0xfc},
47 {0x3706, 0x61},
48 {0x3712, 0x0c},
49 {0x3630, 0x6d},
50 {0x3801, 0xb4},
51
52 {0x3621, 0x04},
53 {0x3604, 0x60},
54 {0x3603, 0xa7},
55 {0x3631, 0x26},
56 {0x3600, 0x04},
57 {0x3620, 0x37},
58 {0x3623, 0x00},
59 {0x3702, 0x9e},
60 {0x3703, 0x5c},
61 {0x3704, 0x40},
62 {0x370d, 0x0f},
63 {0x3713, 0x9f},
64 {0x3714, 0x4c},
65 {0x3710, 0x9e},
66 {0x3801, 0xc4},
67 {0x3605, 0x05},
68 {0x3606, 0x3f},
69 {0x302d, 0x90},
70 {0x370b, 0x40},
71 {0x3716, 0x31},
72 {0x3707, 0x52},
73 {0x380d, 0x74},
74 {0x5181, 0x20},
75 {0x518f, 0x00},
76 {0x4301, 0xff},
77 {0x4303, 0x00},
78 {0x3a00, 0x78},
79 {0x300f, 0x88},
80 {0x3011, 0x28},
81 {0x3a1a, 0x06},
82 {0x3a18, 0x00},
83 {0x3a19, 0x7a},
84 {0x3a13, 0x54},
85 {0x382e, 0x0f},
86 {0x381a, 0x1a},
87 {0x401d, 0x02},
88
89 {0x381c, 0x00},
90 {0x381d, 0x02},
91 {0x381e, 0x04},
92 {0x381f, 0x38},
93 {0x3820, 0x00},
94 {0x3821, 0x98},
95 {0x3800, 0x01},
96 {0x3802, 0x00},
97 {0x3803, 0x0a},
98 {0x3804, 0x07},
99 {0x3805, 0x90},
100 {0x3806, 0x04},
101 {0x3807, 0x40},
102 {0x3808, 0x07},
103 {0x3809, 0x90},
104 {0x380a, 0x04},
105 {0x380b, 0x40},
106 {0x380e, 0x04},
107 {0x380f, 0x50},
108 {0x380c, 0x09},
109 {0x380d, 0x74},
110 {0x3810, 0x08},
111 {0x3811, 0x02},
112
113 {0x5688, 0x03},
114 {0x5684, 0x07},
115 {0x5685, 0xa0},
116 {0x5686, 0x04},
117 {0x5687, 0x43},
118 {0x3011, 0x0a},
119 {0x300f, 0x8a},
120 {0x3017, 0x00},
121 {0x3018, 0x00},
122 {0x4800, 0x24},
123 {0x300e, 0x04},
124 {0x4801, 0x0f},
125
126 {0x300f, 0xc3},
127 {0x3010, 0x00},
128 {0x3011, 0x0a},
129 {0x3012, 0x01},
130
131 {0x3a0f, 0x40},
132 {0x3a10, 0x38},
133 {0x3a1b, 0x48},
134 {0x3a1e, 0x30},
135 {0x3a11, 0x90},
136 {0x3a1f, 0x10},
137
138 {0x3a0e, 0x03},
139 {0x3a0d, 0x04},
140 {0x3a08, 0x14},
141 {0x3a09, 0xc0},
142 {0x3a0a, 0x11},
143 {0x3a0b, 0x40},
144
145 {0x300f, 0xc3},
146 {0x3010, 0x00},
147 {0x3011, 0x0e},
148 {0x3012, 0x02},
149 {0x380c, 0x09},
150 {0x380d, 0xec},
151 {0x3703, 0x61},
152 {0x3704, 0x44},
153 {0x3801, 0xd2},
154
155 {0x3503, 0x17},
156 {0x3500, 0x00},
157 {0x3501, 0x00},
158 {0x3502, 0x00},
159 {0x350a, 0x00},
160 {0x350b, 0x00},
161 {0x5001, 0x4e},
162 {0x5000, 0x5f},
163 {0x3008, 0x02},
164
165 {OV2710_TABLE_END, 0x0000}
166};
167
168static struct ov2710_reg mode_1280x720[] = {
169 {0x3103, 0x93},
170 {0x3008, 0x82},
171 {OV2710_TABLE_WAIT_MS, 5},
172 {0x3008, 0x42},
173 {OV2710_TABLE_WAIT_MS, 5},
174 {0x3017, 0x7f},
175 {0x3018, 0xfc},
176
177 {0x3706, 0x61},
178 {0x3712, 0x0c},
179 {0x3630, 0x6d},
180 {0x3801, 0xb4},
181 {0x3621, 0x04},
182 {0x3604, 0x60},
183 {0x3603, 0xa7},
184 {0x3631, 0x26},
185 {0x3600, 0x04},
186 {0x3620, 0x37},
187 {0x3623, 0x00},
188 {0x3702, 0x9e},
189 {0x3703, 0x5c},
190 {0x3704, 0x40},
191 {0x370d, 0x0f},
192 {0x3713, 0x9f},
193 {0x3714, 0x4c},
194 {0x3710, 0x9e},
195 {0x3801, 0xc4},
196 {0x3605, 0x05},
197 {0x3606, 0x3f},
198 {0x302d, 0x90},
199 {0x370b, 0x40},
200 {0x3716, 0x31},
201 {0x3707, 0x52},
202 {0x380d, 0x74},
203 {0x5181, 0x20},
204 {0x518f, 0x00},
205 {0x4301, 0xff},
206 {0x4303, 0x00},
207 {0x3a00, 0x78},
208 {0x300f, 0x88},
209 {0x3011, 0x28},
210 {0x3a1a, 0x06},
211 {0x3a18, 0x00},
212 {0x3a19, 0x7a},
213 {0x3a13, 0x54},
214 {0x382e, 0x0f},
215 {0x381a, 0x1a},
216 {0x401d, 0x02},
217
218 {0x381c, 0x10},
219 {0x381d, 0xb0},
220 {0x381e, 0x02},
221 {0x381f, 0xec},
222 {0x3800, 0x01},
223 {0x3820, 0x0a},
224 {0x3821, 0x2a},
225 {0x3804, 0x05},
226 {0x3805, 0x10},
227 {0x3802, 0x00},
228 {0x3803, 0x04},
229 {0x3806, 0x02},
230 {0x3807, 0xe0},
231 {0x3808, 0x05},
232 {0x3809, 0x10},
233 {0x380a, 0x02},
234 {0x380b, 0xe0},
235 {0x380e, 0x02},
236 {0x380f, 0xf0},
237 {0x380c, 0x07},
238 {0x380d, 0x00},
239 {0x3810, 0x10},
240 {0x3811, 0x06},
241
242 {0x5688, 0x03},
243 {0x5684, 0x05},
244 {0x5685, 0x00},
245 {0x5686, 0x02},
246 {0x5687, 0xd0},
247
248 {0x3a08, 0x1b},
249 {0x3a09, 0xe6},
250 {0x3a0a, 0x17},
251 {0x3a0b, 0x40},
252 {0x3a0e, 0x01},
253 {0x3a0d, 0x02},
254 {0x3011, 0x0a},
255 {0x300f, 0x8a},
256 {0x3017, 0x00},
257 {0x3018, 0x00},
258 {0x4800, 0x24},
259 {0x300e, 0x04},
260 {0x4801, 0x0f},
261 {0x300f, 0xc3},
262 {0x3a0f, 0x40},
263 {0x3a10, 0x38},
264 {0x3a1b, 0x48},
265 {0x3a1e, 0x30},
266 {0x3a11, 0x90},
267 {0x3a1f, 0x10},
268
269 {0x3010, 0x10},
270 {0x3a0e, 0x02},
271 {0x3a0d, 0x03},
272 {0x3a08, 0x0d},
273 {0x3a09, 0xf3},
274 {0x3a0a, 0x0b},
275 {0x3a0b, 0xa0},
276
277 {0x300f, 0xc3},
278 {0x3011, 0x0e},
279 {0x3012, 0x02},
280 {0x380c, 0x07},
281 {0x380d, 0x6a},
282 {0x3703, 0x5c},
283 {0x3704, 0x40},
284 {0x3801, 0xbc},
285
286 {0x3503, 0x17},
287 {0x3500, 0x00},
288 {0x3501, 0x00},
289 {0x3502, 0x00},
290 {0x350a, 0x00},
291 {0x350b, 0x00},
292 {0x5001, 0x4e},
293 {0x5000, 0x5f},
294 {0x3008, 0x02},
295
296 {OV2710_TABLE_END, 0x0000}
297};
298
299enum {
300 OV2710_MODE_1920x1080,
301 OV2710_MODE_1280x720,
302};
303
304
305static struct ov2710_reg *mode_table[] = {
306 [OV2710_MODE_1920x1080] = mode_1920x1080,
307 [OV2710_MODE_1280x720] = mode_1280x720,
308};
309
310static inline void ov2710_get_frame_length_regs(struct ov2710_reg *regs,
311 u32 frame_length)
312{
313 regs->addr = 0x380e;
314 regs->val = (frame_length >> 8) & 0xff;
315 (regs + 1)->addr = 0x380f;
316 (regs + 1)->val = (frame_length) & 0xff;
317}
318
319static inline void ov2710_get_coarse_time_regs(struct ov2710_reg *regs,
320 u32 coarse_time)
321{
322 regs->addr = 0x3500;
323 regs->val = (coarse_time >> 12) & 0xff;
324 (regs + 1)->addr = 0x3501;
325 (regs + 1)->val = (coarse_time >> 4) & 0xff;
326 (regs + 2)->addr = 0x3502;
327 (regs + 2)->val = (coarse_time & 0xf) << 4;
328}
329
330static inline void ov2710_get_gain_reg(struct ov2710_reg *regs, u16 gain)
331{
332 regs->addr = 0x350b;
333 regs->val = gain;
334}
335
336static int ov2710_read_reg(struct i2c_client *client, u16 addr, u8 *val)
337{
338 int err;
339 struct i2c_msg msg[2];
340 unsigned char data[3];
341
342 if (!client->adapter)
343 return -ENODEV;
344
345 msg[0].addr = client->addr;
346 msg[0].flags = 0;
347 msg[0].len = 2;
348 msg[0].buf = data;
349
350 /* high byte goes out first */
351 data[0] = (u8) (addr >> 8);;
352 data[1] = (u8) (addr & 0xff);
353
354 msg[1].addr = client->addr;
355 msg[1].flags = I2C_M_RD;
356 msg[1].len = 1;
357 msg[1].buf = data + 2;
358
359 err = i2c_transfer(client->adapter, msg, 2);
360
361 if (err != 2)
362
363 return -EINVAL;
364
365 *val = data[2];
366
367 return 0;
368}
369
370static int ov2710_write_reg(struct i2c_client *client, u16 addr, u8 val)
371{
372 int err;
373 struct i2c_msg msg;
374 unsigned char data[3];
375 int retry = 0;
376
377 if (!client->adapter)
378 return -ENODEV;
379
380 data[0] = (u8) (addr >> 8);;
381 data[1] = (u8) (addr & 0xff);
382 data[2] = (u8) (val & 0xff);
383
384 msg.addr = client->addr;
385 msg.flags = 0;
386 msg.len = 3;
387 msg.buf = data;
388
389 do {
390 err = i2c_transfer(client->adapter, &msg, 1);
391 if (err == 1)
392 return 0;
393 retry++;
394 pr_err("ov2710: i2c transfer failed, retrying %x %x\n",
395 addr, val);
396
397 msleep(3);
398 } while (retry <= OV2710_MAX_RETRIES);
399
400 return err;
401}
402
403static int ov2710_write_table(struct i2c_client *client,
404 const struct ov2710_reg table[],
405 const struct ov2710_reg override_list[],
406 int num_override_regs)
407{
408 int err;
409 const struct ov2710_reg *next;
410 int i;
411 u16 val;
412
413 for (next = table; next->addr != OV2710_TABLE_END; next++) {
414 if (next->addr == OV2710_TABLE_WAIT_MS) {
415 msleep(next->val);
416 continue;
417 }
418
419
420 val = next->val;
421
422 /* When an override list is passed in, replace the reg */
423 /* value to write if the reg is in the list */
424 if (override_list) {
425 for (i = 0; i < num_override_regs; i++) {
426 if (next->addr == override_list[i].addr) {
427 val = override_list[i].val;
428 break;
429 }
430 }
431 }
432
433 err = ov2710_write_reg(client, next->addr, val);
434 if (err)
435 return err;
436 }
437 return 0;
438}
439
440static int ov2710_set_mode(struct ov2710_info *info, struct ov2710_mode *mode)
441{
442 int sensor_mode;
443 int err;
444 struct ov2710_reg reg_list[6];
445
446 pr_info("%s: xres %u yres %u framelength %u coarsetime %u gain %u\n",
447 __func__, mode->xres, mode->yres, mode->frame_length,
448 mode->coarse_time, mode->gain);
449
450 if (mode->xres == 1920 && mode->yres == 1080)
451 sensor_mode = OV2710_MODE_1920x1080;
452 else if (mode->xres == 1280 && mode->yres == 720)
453 sensor_mode = OV2710_MODE_1280x720;
454 else {
455 pr_err("%s: invalid resolution supplied to set mode %d %d\n",
456 __func__, mode->xres, mode->yres);
457 return -EINVAL;
458 }
459
460 /* get a list of override regs for the asking frame length, */
461 /* coarse integration time, and gain. */
462 ov2710_get_frame_length_regs(reg_list, mode->frame_length);
463 ov2710_get_coarse_time_regs(reg_list + 2, mode->coarse_time);
464 ov2710_get_gain_reg(reg_list + 5, mode->gain);
465
466 err = ov2710_write_table(info->i2c_client, mode_table[sensor_mode],
467 reg_list, 6);
468 if (err)
469 return err;
470
471 info->mode = sensor_mode;
472 return 0;
473}
474
475static int ov2710_set_frame_length(struct ov2710_info *info, u32 frame_length)
476{
477 struct ov2710_reg reg_list[2];
478 int i = 0;
479 int ret;
480
481 ov2710_get_frame_length_regs(reg_list, frame_length);
482
483 for (i = 0; i < 2; i++) {
484 ret = ov2710_write_reg(info->i2c_client, reg_list[i].addr,
485 reg_list[i].val);
486 if (ret)
487 return ret;
488 }
489
490 return 0;
491}
492
493static int ov2710_set_coarse_time(struct ov2710_info *info, u32 coarse_time)
494{
495 int ret;
496
497 struct ov2710_reg reg_list[3];
498 int i = 0;
499
500 ov2710_get_coarse_time_regs(reg_list, coarse_time);
501
502 ret = ov2710_write_reg(info->i2c_client, 0x3212, 0x01);
503 if (ret)
504 return ret;
505
506 for (i = 0; i < 3; i++) {
507 ret = ov2710_write_reg(info->i2c_client, reg_list[i].addr,
508 reg_list[i].val);
509 if (ret)
510 return ret;
511 }
512
513 ret = ov2710_write_reg(info->i2c_client, 0x3212, 0x11);
514 if (ret)
515 return ret;
516
517 ret = ov2710_write_reg(info->i2c_client, 0x3212, 0xa1);
518 if (ret)
519 return ret;
520
521 return 0;
522}
523
524static int ov2710_set_gain(struct ov2710_info *info, u16 gain)
525{
526 int ret;
527 struct ov2710_reg reg_list;
528
529 ov2710_get_gain_reg(&reg_list, gain);
530
531 ret = ov2710_write_reg(info->i2c_client, reg_list.addr, reg_list.val);
532
533 return ret;
534}
535
536static int ov2710_get_status(struct ov2710_info *info, u8 *status)
537{
538 int err;
539
540 *status = 0;
541 err = ov2710_read_reg(info->i2c_client, 0x002, status);
542 return err;
543}
544
545
546static long ov2710_ioctl(struct file *file,
547 unsigned int cmd, unsigned long arg)
548{
549 int err;
550 struct ov2710_info *info = file->private_data;
551
552 switch (cmd) {
553 case OV2710_IOCTL_SET_MODE:
554 {
555 struct ov2710_mode mode;
556 if (copy_from_user(&mode,
557 (const void __user *)arg,
558 sizeof(struct ov2710_mode))) {
559 return -EFAULT;
560 }
561
562 return ov2710_set_mode(info, &mode);
563 }
564 case OV2710_IOCTL_SET_FRAME_LENGTH:
565 return ov2710_set_frame_length(info, (u32)arg);
566 case OV2710_IOCTL_SET_COARSE_TIME:
567 return ov2710_set_coarse_time(info, (u32)arg);
568 case OV2710_IOCTL_SET_GAIN:
569 return ov2710_set_gain(info, (u16)arg);
570 case OV2710_IOCTL_GET_STATUS:
571 {
572 u8 status;
573
574 err = ov2710_get_status(info, &status);
575 if (err)
576 return err;
577 if (copy_to_user((void __user *)arg, &status,
578 2)) {
579 return -EFAULT;
580 }
581 return 0;
582 }
583 default:
584 return -EINVAL;
585 }
586 return 0;
587}
588
589static struct ov2710_info *info;
590
591static int ov2710_open(struct inode *inode, struct file *file)
592{
593 u8 status;
594
595 file->private_data = info;
596 if (info->pdata && info->pdata->power_on)
597 info->pdata->power_on();
598 ov2710_get_status(info, &status);
599 return 0;
600}
601
602int ov2710_release(struct inode *inode, struct file *file)
603{
604 if (info->pdata && info->pdata->power_off)
605 info->pdata->power_off();
606 file->private_data = NULL;
607 return 0;
608}
609
610
611static const struct file_operations ov2710_fileops = {
612 .owner = THIS_MODULE,
613 .open = ov2710_open,
614 .unlocked_ioctl = ov2710_ioctl,
615 .release = ov2710_release,
616};
617
618static struct miscdevice ov2710_device = {
619 .minor = MISC_DYNAMIC_MINOR,
620 .name = "ov2710",
621 .fops = &ov2710_fileops,
622};
623
624static int ov2710_probe(struct i2c_client *client,
625 const struct i2c_device_id *id)
626{
627 int err;
628
629 pr_info("ov2710: probing sensor.\n");
630
631 info = kzalloc(sizeof(struct ov2710_info), GFP_KERNEL);
632 if (!info) {
633 pr_err("ov2710: Unable to allocate memory!\n");
634 return -ENOMEM;
635 }
636
637 err = misc_register(&ov2710_device);
638 if (err) {
639 pr_err("ov2710: Unable to register misc device!\n");
640 kfree(info);
641 return err;
642 }
643
644 info->pdata = client->dev.platform_data;
645 info->i2c_client = client;
646
647 i2c_set_clientdata(client, info);
648 return 0;
649}
650
651static int ov2710_remove(struct i2c_client *client)
652{
653 struct ov2710_info *info;
654 info = i2c_get_clientdata(client);
655 misc_deregister(&ov2710_device);
656 kfree(info);
657 return 0;
658}
659
660static const struct i2c_device_id ov2710_id[] = {
661 { "ov2710", 0 },
662 { },
663};
664
665MODULE_DEVICE_TABLE(i2c, ov2710_id);
666
667static struct i2c_driver ov2710_i2c_driver = {
668 .driver = {
669 .name = "ov2710",
670 .owner = THIS_MODULE,
671 },
672 .probe = ov2710_probe,
673 .remove = ov2710_remove,
674 .id_table = ov2710_id,
675};
676
677static int __init ov2710_init(void)
678{
679 pr_info("ov2710 sensor driver loading\n");
680 return i2c_add_driver(&ov2710_i2c_driver);
681}
682
683static void __exit ov2710_exit(void)
684{
685 i2c_del_driver(&ov2710_i2c_driver);
686}
687
688module_init(ov2710_init);
689module_exit(ov2710_exit);
690
diff --git a/drivers/media/video/tegra/ov5650.c b/drivers/media/video/tegra/ov5650.c
new file mode 100644
index 00000000000..3adb46a3bb8
--- /dev/null
+++ b/drivers/media/video/tegra/ov5650.c
@@ -0,0 +1,1520 @@
1/*
2 * ov5650.c - ov5650 sensor driver
3 *
4 * Copyright (C) 2011 Google Inc.
5 *
6 * Contributors:
7 * Rebecca Schultz Zavin <rebecca@android.com>
8 *
9 * Leverage OV9640.c
10 *
11 * This file is licensed under the terms of the GNU General Public License
12 * version 2. This program is licensed "as is" without any warranty of any
13 * kind, whether express or implied.
14 */
15
16#include <linux/delay.h>
17#include <linux/fs.h>
18#include <linux/i2c.h>
19#include <linux/miscdevice.h>
20#include <linux/slab.h>
21#include <linux/uaccess.h>
22#include <media/ov5650.h>
23#include <media/tegra_camera.h>
24
25#define SIZEOF_I2C_TRANSBUF 32
26
27struct ov5650_reg {
28 u16 addr;
29 u16 val;
30};
31
32struct ov5650_sensor {
33 struct i2c_client *i2c_client;
34 struct ov5650_platform_data *pdata;
35};
36
37struct ov5650_info {
38 int mode;
39 enum StereoCameraMode camera_mode;
40 struct ov5650_sensor left;
41 struct ov5650_sensor right;
42 u8 i2c_trans_buf[SIZEOF_I2C_TRANSBUF];
43};
44
45static struct ov5650_info *stereo_ov5650_info;
46
47#define OV5650_TABLE_WAIT_MS 0
48#define OV5650_TABLE_END 1
49#define OV5650_MAX_RETRIES 3
50
51static struct ov5650_reg tp_none_seq[] = {
52 {0x5046, 0x00},
53 {OV5650_TABLE_END, 0x0000}
54};
55
56static struct ov5650_reg tp_cbars_seq[] = {
57 {0x503D, 0xC0},
58 {0x503E, 0x00},
59 {0x5046, 0x01},
60 {OV5650_TABLE_END, 0x0000}
61};
62
63static struct ov5650_reg tp_checker_seq[] = {
64 {0x503D, 0xC0},
65 {0x503E, 0x0A},
66 {0x5046, 0x01},
67 {OV5650_TABLE_END, 0x0000}
68};
69
70static struct ov5650_reg *test_pattern_modes[] = {
71 tp_none_seq,
72 tp_cbars_seq,
73 tp_checker_seq,
74};
75
76static struct ov5650_reg reset_seq[] = {
77 {0x3008, 0x82},
78 {OV5650_TABLE_WAIT_MS, 5},
79 {0x3008, 0x42},
80 {OV5650_TABLE_WAIT_MS, 5},
81 {OV5650_TABLE_END, 0x0000},
82};
83
84static struct ov5650_reg mode_start[] = {
85 {0x3103, 0x93},
86 {0x3017, 0xff},
87 {0x3018, 0xfc},
88
89 {0x3600, 0x50},
90 {0x3601, 0x0d},
91 {0x3604, 0x50},
92 {0x3605, 0x04},
93 {0x3606, 0x3f},
94 {0x3612, 0x1a},
95 {0x3630, 0x22},
96 {0x3631, 0x22},
97 {0x3702, 0x3a},
98 {0x3704, 0x18},
99 {0x3705, 0xda},
100 {0x3706, 0x41},
101 {0x370a, 0x80},
102 {0x370b, 0x40},
103 {0x370e, 0x00},
104 {0x3710, 0x28},
105 {0x3712, 0x13},
106 {0x3830, 0x50},
107 {0x3a18, 0x00},
108 {0x3a19, 0xf8},
109 {0x3a00, 0x38},
110
111
112 {0x3603, 0xa7},
113 {0x3615, 0x50},
114 {0x3620, 0x56},
115 {0x3810, 0x00},
116 {0x3836, 0x00},
117 {0x3a1a, 0x06},
118 {0x4000, 0x01},
119 {0x401c, 0x48},
120 {0x401d, 0x08},
121 {0x5000, 0x00},
122 {0x5001, 0x00},
123 {0x5002, 0x00},
124 {0x503d, 0x00},
125 {0x5046, 0x00},
126
127 {0x300f, 0x8f},
128
129 {0x3010, 0x10},
130 {0x3011, 0x14},
131 {0x3012, 0x02},
132 {0x3815, 0x82},
133 {0x3503, 0x33},
134 {0x3613, 0x44},
135 {OV5650_TABLE_END, 0x0},
136};
137
138static struct ov5650_reg mode_2592x1944[] = {
139 {0x3621, 0x2f},
140
141 {0x3632, 0x55},
142 {0x3703, 0xe6},
143 {0x370c, 0xa0},
144 {0x370d, 0x04},
145 {0x3713, 0x2f},
146 {0x3800, 0x02},
147 {0x3801, 0x58},
148 {0x3802, 0x00},
149 {0x3803, 0x0c},
150 {0x3804, 0x0a},
151 {0x3805, 0x20},
152 {0x3806, 0x07},
153 {0x3807, 0xa0},
154 {0x3808, 0x0a},
155
156 {0x3809, 0x20},
157
158 {0x380a, 0x07},
159
160 {0x380b, 0xa0},
161
162 {0x380c, 0x0c},
163
164 {0x380d, 0xb4},
165
166 {0x380e, 0x07},
167
168 {0x380f, 0xb0},
169
170 {0x3818, 0xc0},
171 {0x381a, 0x3c},
172 {0x3a0d, 0x06},
173 {0x3c01, 0x00},
174 {0x3007, 0x3f},
175 {0x5059, 0x80},
176 {0x3003, 0x03},
177 {0x3500, 0x00},
178 {0x3501, 0x7a},
179
180 {0x3502, 0xd0},
181
182 {0x350a, 0x00},
183 {0x350b, 0x00},
184 {0x401d, 0x08},
185 {0x4801, 0x0f},
186 {0x300e, 0x0c},
187 {0x4803, 0x50},
188 {0x4800, 0x34},
189 {OV5650_TABLE_END, 0x0000}
190};
191
192static struct ov5650_reg mode_1296x972[] = {
193 {0x3621, 0xaf},
194
195 {0x3632, 0x5a},
196 {0x3703, 0xb0},
197 {0x370c, 0xc5},
198 {0x370d, 0x42},
199 {0x3713, 0x2f},
200 {0x3800, 0x03},
201 {0x3801, 0x3c},
202 {0x3802, 0x00},
203 {0x3803, 0x06},
204 {0x3804, 0x05},
205 {0x3805, 0x10},
206 {0x3806, 0x03},
207 {0x3807, 0xd0},
208 {0x3808, 0x05},
209
210 {0x3809, 0x10},
211
212 {0x380a, 0x03},
213
214 {0x380b, 0xd0},
215
216 {0x380c, 0x08},
217
218 {0x380d, 0xa8},
219
220 {0x380e, 0x05},
221
222 {0x380f, 0xa4},
223
224 {0x3818, 0xc1},
225 {0x381a, 0x00},
226 {0x3a0d, 0x08},
227 {0x3c01, 0x00},
228 {0x3007, 0x3b},
229 {0x5059, 0x80},
230 {0x3003, 0x03},
231 {0x3500, 0x00},
232
233 {0x3501, 0x5a},
234 {0x3502, 0x10},
235 {0x350a, 0x00},
236 {0x350b, 0x10},
237 {0x401d, 0x08},
238 {0x4801, 0x0f},
239 {0x300e, 0x0c},
240 {0x4803, 0x50},
241 {0x4800, 0x34},
242 {OV5650_TABLE_END, 0x0000}
243};
244
245static struct ov5650_reg mode_2080x1164[] = {
246 {0x3103, 0x93},
247 {0x3007, 0x3b},
248 {0x3017, 0xff},
249 {0x3018, 0xfc},
250
251 {0x3600, 0x54},
252 {0x3601, 0x05},
253 {0x3603, 0xa7},
254 {0x3604, 0x40},
255 {0x3605, 0x04},
256 {0x3606, 0x3f},
257 {0x3612, 0x1a},
258 {0x3613, 0x44},
259 {0x3615, 0x52},
260 {0x3620, 0x56},
261 {0x3623, 0x01},
262 {0x3630, 0x22},
263 {0x3631, 0x36},
264 {0x3632, 0x5f},
265 {0x3633, 0x24},
266
267 {0x3702, 0x3a},
268 {0x3704, 0x18},
269 {0x3706, 0x41},
270 {0x370b, 0x40},
271 {0x370e, 0x00},
272 {0x3710, 0x28},
273 {0x3711, 0x24},
274 {0x3712, 0x13},
275
276 {0x3810, 0x00},
277 {0x3815, 0x82},
278 {0x3830, 0x50},
279 {0x3836, 0x00},
280
281 {0x3a1a, 0x06},
282 {0x3a18, 0x00},
283 {0x3a19, 0xf8},
284 {0x3a00, 0x38},
285
286 {0x3a0d, 0x06},
287 {0x3c01, 0x34},
288
289 {0x401f, 0x03},
290 {0x4000, 0x05},
291 {0x401d, 0x08},
292 {0x4001, 0x02},
293
294 {0x5000, 0x00},
295 {0x5001, 0x00},
296 {0x5002, 0x00},
297 {0x503d, 0x00},
298 {0x5046, 0x00},
299
300 {0x300f, 0x8f},
301
302 {0x3010, 0x10},
303 {0x3011, 0x14},
304 {0x3012, 0x02},
305 {0x3503, 0x33},
306
307
308 {0x3621, 0x2f},
309
310 {0x3703, 0xe6},
311 {0x370c, 0x00},
312 {0x370d, 0x04},
313 {0x3713, 0x22},
314 {0x3714, 0x27},
315 {0x3705, 0xda},
316 {0x370a, 0x80},
317
318 {0x3800, 0x02},
319 {0x3801, 0x12},
320 {0x3802, 0x00},
321 {0x3803, 0x0a},
322 {0x3804, 0x08},
323 {0x3805, 0x20},
324 {0x3806, 0x04},
325 {0x3807, 0x92},
326 {0x3808, 0x08},
327
328 {0x3809, 0x20},
329
330 {0x380a, 0x04},
331
332 {0x380b, 0x92},
333
334 {0x380c, 0x0a},
335
336 {0x380d, 0x96},
337
338 {0x380e, 0x04},
339
340 {0x380f, 0x9e},
341
342 {0x3818, 0xc0},
343 {0x381a, 0x3c},
344 {0x381c, 0x31},
345 {0x381d, 0x8e},
346 {0x381e, 0x04},
347 {0x381f, 0x92},
348 {0x3820, 0x04},
349 {0x3821, 0x19},
350 {0x3824, 0x01},
351 {0x3827, 0x0a},
352 {0x401c, 0x46},
353
354 {0x3003, 0x03},
355 {0x3500, 0x00},
356 {0x3501, 0x49},
357 {0x3502, 0xa0},
358 {0x350a, 0x00},
359 {0x350b, 0x00},
360 {0x4801, 0x0f},
361 {0x300e, 0x0c},
362 {0x4803, 0x50},
363 {0x4800, 0x34},
364
365 {OV5650_TABLE_END, 0x0000}
366};
367
368static struct ov5650_reg mode_1920x1080[] = {
369 {0x3103, 0x93},
370 {0x3007, 0x3b},
371 {0x3017, 0xff},
372 {0x3018, 0xfc},
373
374 {0x3600, 0x54},
375 {0x3601, 0x05},
376 {0x3603, 0xa7},
377 {0x3604, 0x40},
378 {0x3605, 0x04},
379 {0x3606, 0x3f},
380 {0x3612, 0x1a},
381 {0x3613, 0x44},
382 {0x3615, 0x52},
383 {0x3620, 0x56},
384 {0x3623, 0x01},
385 {0x3630, 0x22},
386 {0x3631, 0x36},
387 {0x3632, 0x5f},
388 {0x3633, 0x24},
389
390 {0x3702, 0x3a},
391 {0x3704, 0x18},
392 {0x3706, 0x41},
393 {0x370b, 0x40},
394 {0x370e, 0x00},
395 {0x3710, 0x28},
396 {0x3711, 0x24},
397 {0x3712, 0x13},
398
399 {0x3810, 0x00},
400 {0x3815, 0x82},
401
402 {0x3830, 0x50},
403 {0x3836, 0x00},
404
405 {0x3a1a, 0x06},
406 {0x3a18, 0x00},
407 {0x3a19, 0xf8},
408 {0x3a00, 0x38},
409 {0x3a0d, 0x06},
410 {0x3c01, 0x34},
411
412 {0x401f, 0x03},
413 {0x4000, 0x05},
414 {0x401d, 0x08},
415 {0x4001, 0x02},
416
417 {0x5000, 0x00},
418 {0x5001, 0x00},
419 {0x5002, 0x00},
420 {0x503d, 0x00},
421 {0x5046, 0x00},
422
423 {0x300f, 0x8f},
424 {0x3010, 0x10},
425 {0x3011, 0x14},
426 {0x3012, 0x02},
427 {0x3503, 0x33},
428
429 {0x3621, 0x2f},
430 {0x3703, 0xe6},
431 {0x370c, 0x00},
432 {0x370d, 0x04},
433 {0x3713, 0x22},
434 {0x3714, 0x27},
435 {0x3705, 0xda},
436 {0x370a, 0x80},
437
438 {0x3800, 0x02},
439 {0x3801, 0x94},
440 {0x3802, 0x00},
441 {0x3803, 0x0c},
442 {0x3804, 0x07},
443 {0x3805, 0x80},
444 {0x3806, 0x04},
445 {0x3807, 0x40},
446 {0x3808, 0x07},
447 {0x3809, 0x80},
448 {0x380a, 0x04},
449 {0x380b, 0x40},
450 {0x380c, 0x0a},
451 {0x380d, 0x84},
452 {0x380e, 0x04},
453 {0x380f, 0xa4},
454 {0x3818, 0xc0},
455 {0x381a, 0x3c},
456 {0x381c, 0x31},
457 {0x381d, 0xa4},
458 {0x381e, 0x04},
459 {0x381f, 0x60},
460 {0x3820, 0x03},
461 {0x3821, 0x1a},
462 {0x3824, 0x01},
463 {0x3827, 0x0a},
464 {0x401c, 0x46},
465
466 {0x3003, 0x03},
467 {0x3500, 0x00},
468 {0x3501, 0x49},
469 {0x3502, 0xa0},
470 {0x350a, 0x00},
471 {0x350b, 0x00},
472 {0x4801, 0x0f},
473 {0x300e, 0x0c},
474 {0x4803, 0x50},
475 {0x4800, 0x34},
476
477 {OV5650_TABLE_END, 0x0000}
478};
479
480
481static struct ov5650_reg mode_1264x704[] = {
482 {0x3600, 0x54},
483 {0x3601, 0x05},
484 {0x3604, 0x40},
485 {0x3705, 0xdb},
486 {0x370a, 0x81},
487 {0x3615, 0x52},
488 {0x3810, 0x40},
489 {0x3836, 0x41},
490 {0x4000, 0x05},
491 {0x401c, 0x42},
492 {0x401d, 0x08},
493 {0x5046, 0x09},
494 {0x3010, 0x00},
495 {0x3503, 0x00},
496 {0x3613, 0xc4},
497
498 {0x3621, 0xaf},
499
500 {0x3632, 0x55},
501 {0x3703, 0x9a},
502 {0x370c, 0x00},
503 {0x370d, 0x42},
504 {0x3713, 0x22},
505 {0x3800, 0x02},
506 {0x3801, 0x54},
507 {0x3802, 0x00},
508 {0x3803, 0x0c},
509 {0x3804, 0x05},
510 {0x3805, 0x00},
511 {0x3806, 0x02},
512 {0x3807, 0xd0},
513 {0x3808, 0x05},
514
515 {0x3809, 0x00},
516
517 {0x380a, 0x02},
518
519 {0x380b, 0xd0},
520
521 {0x380c, 0x08},
522
523 {0x380d, 0x72},
524
525 {0x380e, 0x02},
526
527 {0x380f, 0xe4},
528
529 {0x3818, 0xc1},
530 {0x381a, 0x3c},
531 {0x3a0d, 0x06},
532 {0x3c01, 0x34},
533 {0x3007, 0x3b},
534 {0x5059, 0x80},
535 {0x3003, 0x03},
536 {0x3500, 0x04},
537 {0x3501, 0xa5},
538
539 {0x3502, 0x10},
540
541 {0x350a, 0x00},
542 {0x350b, 0x00},
543 {0x4801, 0x0f},
544 {0x300e, 0x0c},
545 {0x4803, 0x50},
546 {0x4800, 0x24},
547 {0x300f, 0x8b},
548
549 {0x3711, 0x24},
550 {0x3713, 0x92},
551 {0x3714, 0x17},
552 {0x381c, 0x10},
553 {0x381d, 0x82},
554 {0x381e, 0x05},
555 {0x381f, 0xc0},
556 {0x3821, 0x20},
557 {0x3824, 0x23},
558 {0x3825, 0x2c},
559 {0x3826, 0x00},
560 {0x3827, 0x0c},
561 {0x3623, 0x01},
562 {0x3633, 0x24},
563 {0x3632, 0x5f},
564 {0x401f, 0x03},
565
566 {OV5650_TABLE_END, 0x0000}
567};
568
569static struct ov5650_reg mode_320x240[] = {
570 {0x3103, 0x93},
571 {0x3b07, 0x0c},
572 {0x3017, 0xff},
573 {0x3018, 0xfc},
574 {0x3706, 0x41},
575 {0x3613, 0xc4},
576 {0x370d, 0x42},
577 {0x3703, 0x9a},
578 {0x3630, 0x22},
579 {0x3605, 0x04},
580 {0x3606, 0x3f},
581 {0x3712, 0x13},
582 {0x370e, 0x00},
583 {0x370b, 0x40},
584 {0x3600, 0x54},
585 {0x3601, 0x05},
586 {0x3713, 0x22},
587 {0x3714, 0x27},
588 {0x3631, 0x22},
589 {0x3612, 0x1a},
590 {0x3604, 0x40},
591 {0x3705, 0xdc},
592 {0x370a, 0x83},
593 {0x370c, 0xc8},
594 {0x3710, 0x28},
595 {0x3702, 0x3a},
596 {0x3704, 0x18},
597 {0x3a18, 0x00},
598 {0x3a19, 0xf8},
599 {0x3a00, 0x38},
600 {0x3800, 0x02},
601 {0x3801, 0x54},
602 {0x3803, 0x0c},
603 {0x380c, 0x0c},
604 {0x380d, 0xb4},
605 {0x380e, 0x07},
606 {0x380f, 0xb0},
607 {0x3830, 0x50},
608 {0x3a08, 0x12},
609 {0x3a09, 0x70},
610 {0x3a0a, 0x0f},
611 {0x3a0b, 0x60},
612 {0x3a0d, 0x06},
613 {0x3a0e, 0x06},
614 {0x3a13, 0x54},
615 {0x3815, 0x82},
616 {0x5059, 0x80},
617 {0x3615, 0x52},
618 {0x505a, 0x0a},
619 {0x505b, 0x2e},
620 {0x3713, 0x92},
621 {0x3714, 0x17},
622 {0x3803, 0x0a},
623 {0x3804, 0x05},
624 {0x3805, 0x00},
625 {0x3806, 0x01},
626 {0x3807, 0x00},
627 {0x3808, 0x01},
628 {0x3809, 0x40},
629 {0x380a, 0x01},
630 {0x380b, 0x00},
631 {0x380c, 0x0a},
632
633 {0x380d, 0x04},
634
635 {0x380e, 0x01},
636
637 {0x380f, 0x38},
638
639 {0x3815, 0x81},
640 {0x3824, 0x23},
641 {0x3825, 0x20},
642 {0x3826, 0x00},
643 {0x3827, 0x08},
644 {0x370d, 0xc2},
645 {0x3a08, 0x17},
646 {0x3a09, 0x64},
647 {0x3a0a, 0x13},
648 {0x3a0b, 0x80},
649 {0x3a00, 0x58},
650 {0x3a1a, 0x06},
651 {0x3503, 0x33},
652 {0x3623, 0x01},
653 {0x3633, 0x24},
654 {0x3c01, 0x34},
655 {0x3c04, 0x28},
656 {0x3c05, 0x98},
657 {0x3c07, 0x07},
658 {0x3c09, 0xc2},
659 {0x4000, 0x05},
660 {0x401d, 0x08},
661 {0x4001, 0x02},
662 {0x401c, 0x42},
663 {0x5046, 0x09},
664 {0x3810, 0x40},
665 {0x3836, 0x41},
666 {0x505f, 0x04},
667 {0x5000, 0x06},
668 {0x5001, 0x00},
669 {0x5002, 0x02},
670 {0x503d, 0x00},
671 {0x5901, 0x08},
672 {0x585a, 0x01},
673 {0x585b, 0x2c},
674 {0x585c, 0x01},
675 {0x585d, 0x93},
676 {0x585e, 0x01},
677 {0x585f, 0x90},
678 {0x5860, 0x01},
679 {0x5861, 0x0d},
680 {0x5180, 0xc0},
681 {0x5184, 0x00},
682 {0x470a, 0x00},
683 {0x470b, 0x00},
684 {0x470c, 0x00},
685 {0x300f, 0x8e},
686 {0x3603, 0xa7},
687 {0x3632, 0x55},
688 {0x3620, 0x56},
689 {0x3621, 0xaf},
690 {0x3818, 0xc3},
691 {0x3631, 0x36},
692 {0x3632, 0x5f},
693 {0x3711, 0x24},
694 {0x401f, 0x03},
695
696 {0x3011, 0x14},
697 {0x3007, 0x3B},
698 {0x300f, 0x8f},
699 {0x4801, 0x0f},
700 {0x3003, 0x03},
701 {0x300e, 0x0c},
702 {0x3010, 0x15},
703 {0x4803, 0x50},
704 {0x4800, 0x24},
705 {0x4837, 0x40},
706 {0x3815, 0x82},
707
708 {OV5650_TABLE_END, 0x0000}
709};
710
711static struct ov5650_reg mode_end[] = {
712 {0x3212, 0x00},
713 {0x3003, 0x01},
714 {0x3212, 0x10},
715 {0x3212, 0xa0},
716 {0x3008, 0x02},
717
718 {OV5650_TABLE_END, 0x0000}
719};
720
721enum {
722 OV5650_MODE_2592x1944,
723 OV5650_MODE_1296x972,
724 OV5650_MODE_2080x1164,
725 OV5650_MODE_1920x1080,
726 OV5650_MODE_1264x704,
727 OV5650_MODE_320x240,
728 OV5650_MODE_INVALID
729};
730
731static struct ov5650_reg *mode_table[] = {
732 [OV5650_MODE_2592x1944] = mode_2592x1944,
733 [OV5650_MODE_1296x972] = mode_1296x972,
734 [OV5650_MODE_2080x1164] = mode_2080x1164,
735 [OV5650_MODE_1920x1080] = mode_1920x1080,
736 [OV5650_MODE_1264x704] = mode_1264x704,
737 [OV5650_MODE_320x240] = mode_320x240
738};
739
740static inline void ov5650_get_frame_length_regs(struct ov5650_reg *regs,
741 u32 frame_length)
742{
743 regs->addr = 0x380e;
744 regs->val = (frame_length >> 8) & 0xff;
745 (regs + 1)->addr = 0x380f;
746 (regs + 1)->val = (frame_length) & 0xff;
747}
748
749static inline void ov5650_get_coarse_time_regs(struct ov5650_reg *regs,
750 u32 coarse_time)
751{
752 regs->addr = 0x3500;
753 regs->val = (coarse_time >> 12) & 0xff;
754 (regs + 1)->addr = 0x3501;
755 (regs + 1)->val = (coarse_time >> 4) & 0xff;
756 (regs + 2)->addr = 0x3502;
757 (regs + 2)->val = (coarse_time & 0xf) << 4;
758}
759
760static inline void ov5650_get_gain_reg(struct ov5650_reg *regs, u16 gain)
761{
762 regs->addr = 0x350b;
763 regs->val = gain;
764}
765
766static int ov5650_read_reg(struct i2c_client *client, u16 addr, u8 *val)
767{
768 int err;
769 struct i2c_msg msg[2];
770 unsigned char data[3];
771
772 if (!client->adapter)
773 return -ENODEV;
774
775 msg[0].addr = client->addr;
776 msg[0].flags = 0;
777 msg[0].len = 2;
778 msg[0].buf = data;
779
780 /* high byte goes out first */
781 data[0] = (u8) (addr >> 8);
782 data[1] = (u8) (addr & 0xff);
783
784 msg[1].addr = client->addr;
785 msg[1].flags = I2C_M_RD;
786 msg[1].len = 1;
787 msg[1].buf = data + 2;
788
789 err = i2c_transfer(client->adapter, msg, 2);
790
791 if (err != 1)
792 return -EINVAL;
793
794 *val = data[2];
795
796 return 0;
797}
798
799static int ov5650_read_reg_helper(struct ov5650_info *info,
800 u16 addr, u8 *val)
801{
802 int ret;
803 switch (info->camera_mode) {
804 case Main:
805 case StereoCameraMode_Left:
806 ret = ov5650_read_reg(info->left.i2c_client, addr, val);
807 break;
808 case StereoCameraMode_Stereo:
809 ret = ov5650_read_reg(info->left.i2c_client, addr, val);
810 if (ret)
811 break;
812 ret = ov5650_read_reg(info->right.i2c_client, addr, val);
813 break;
814 case StereoCameraMode_Right:
815 ret = ov5650_read_reg(info->right.i2c_client, addr, val);
816 break;
817 default:
818 return -1;
819 }
820 return ret;
821}
822
823static int ov5650_write_reg(struct i2c_client *client, u16 addr, u8 val)
824{
825 int err;
826 struct i2c_msg msg;
827 unsigned char data[3];
828
829 if (!client->adapter)
830 return -ENODEV;
831
832 data[0] = (u8) (addr >> 8);
833 data[1] = (u8) (addr & 0xff);
834 data[2] = (u8) (val & 0xff);
835
836 msg.addr = client->addr;
837 msg.flags = 0;
838 msg.len = 3;
839 msg.buf = data;
840
841 err = i2c_transfer(client->adapter, &msg, 1);
842 if (err == 1)
843 return 0;
844
845 pr_err("ov5650: i2c transfer failed, retrying %x %x\n", addr, val);
846
847 return err;
848}
849
850static int ov5650_write_reg_helper(struct ov5650_info *info,
851 u16 addr, u8 val)
852{
853 int ret;
854 switch (info->camera_mode) {
855 case Main:
856 case StereoCameraMode_Left:
857 ret = ov5650_write_reg(info->left.i2c_client, addr, val);
858 break;
859 case StereoCameraMode_Stereo:
860 ret = ov5650_write_reg(info->left.i2c_client, addr, val);
861 if (ret)
862 break;
863 ret = ov5650_write_reg(info->right.i2c_client, addr, val);
864 break;
865 case StereoCameraMode_Right:
866 ret = ov5650_write_reg(info->right.i2c_client, addr, val);
867 break;
868 default:
869 return -1;
870 }
871 return ret;
872}
873
874static int ov5650_write_bulk_reg(struct i2c_client *client, u8 *data, int len)
875{
876 int err;
877 struct i2c_msg msg;
878
879 if (!client->adapter)
880 return -ENODEV;
881
882 msg.addr = client->addr;
883 msg.flags = 0;
884 msg.len = len;
885 msg.buf = data;
886
887 err = i2c_transfer(client->adapter, &msg, 1);
888 if (err == 1)
889 return 0;
890
891 pr_err("ov5650: i2c bulk transfer failed at %x\n",
892 (int)data[0] << 8 | data[1]);
893
894 return err;
895}
896
897static int ov5650_write_bulk_reg_helper(struct ov5650_info *info, int len)
898{
899 int ret;
900 switch (info->camera_mode) {
901 case Main:
902 case StereoCameraMode_Left:
903 ret = ov5650_write_bulk_reg(info->left.i2c_client,
904 info->i2c_trans_buf, len);
905 break;
906 case StereoCameraMode_Stereo:
907 ret = ov5650_write_bulk_reg(info->left.i2c_client,
908 info->i2c_trans_buf, len);
909 if (ret)
910 break;
911 ret = ov5650_write_bulk_reg(info->right.i2c_client,
912 info->i2c_trans_buf, len);
913 break;
914 case StereoCameraMode_Right:
915 ret = ov5650_write_bulk_reg(info->right.i2c_client,
916 info->i2c_trans_buf, len);
917 break;
918 default:
919 return -1;
920 }
921 return ret;
922}
923
924static int ov5650_write_table(struct ov5650_info *info,
925 const struct ov5650_reg table[],
926 const struct ov5650_reg override_list[],
927 int num_override_regs)
928{
929 int err;
930 const struct ov5650_reg *next, *n_next;
931 u8 *b_ptr = info->i2c_trans_buf;
932 unsigned int buf_filled = 0;
933 unsigned int i;
934 u16 val;
935
936 for (next = table; next->addr != OV5650_TABLE_END; next++) {
937 if (next->addr == OV5650_TABLE_WAIT_MS) {
938 msleep(next->val);
939 continue;
940 }
941
942 val = next->val;
943 /* When an override list is passed in, replace the reg */
944 /* value to write if the reg is in the list */
945 if (override_list) {
946 for (i = 0; i < num_override_regs; i++) {
947 if (next->addr == override_list[i].addr) {
948 val = override_list[i].val;
949 break;
950 }
951 }
952 }
953
954 if (!buf_filled) {
955 b_ptr = info->i2c_trans_buf;
956 *b_ptr++ = next->addr >> 8;
957 *b_ptr++ = next->addr & 0xff;
958 buf_filled = 2;
959 }
960 *b_ptr++ = val;
961 buf_filled++;
962
963 n_next = next + 1;
964 if (n_next->addr != OV5650_TABLE_END &&
965 n_next->addr != OV5650_TABLE_WAIT_MS &&
966 buf_filled < SIZEOF_I2C_TRANSBUF &&
967 n_next->addr == next->addr + 1) {
968 continue;
969 }
970
971 err = ov5650_write_bulk_reg_helper(info, buf_filled);
972 if (err)
973 return err;
974
975 buf_filled = 0;
976 }
977 return 0;
978}
979
980static int ov5650_set_mode(struct ov5650_info *info, struct ov5650_mode *mode)
981{
982 int sensor_mode;
983 int err;
984 struct ov5650_reg reg_list[6];
985
986 pr_info("%s: xres %u yres %u framelength %u coarsetime %u gain %u\n",
987 __func__, mode->xres, mode->yres, mode->frame_length,
988 mode->coarse_time, mode->gain);
989 if (mode->xres == 2592 && mode->yres == 1944)
990 sensor_mode = OV5650_MODE_2592x1944;
991 else if (mode->xres == 1296 && mode->yres == 972)
992 sensor_mode = OV5650_MODE_1296x972;
993 else if (mode->xres == 2080 && mode->yres == 1164)
994 sensor_mode = OV5650_MODE_2080x1164;
995 else if (mode->xres == 1920 && mode->yres == 1080)
996 sensor_mode = OV5650_MODE_1920x1080;
997 else if (mode->xres == 1264 && mode->yres == 704)
998 sensor_mode = OV5650_MODE_1264x704;
999 else if (mode->xres == 320 && mode->yres == 240)
1000 sensor_mode = OV5650_MODE_320x240;
1001 else {
1002 pr_err("%s: invalid resolution supplied to set mode %d %d\n",
1003 __func__, mode->xres, mode->yres);
1004 return -EINVAL;
1005 }
1006
1007 /* get a list of override regs for the asking frame length, */
1008 /* coarse integration time, and gain. */
1009 ov5650_get_frame_length_regs(reg_list, mode->frame_length);
1010 ov5650_get_coarse_time_regs(reg_list + 2, mode->coarse_time);
1011 ov5650_get_gain_reg(reg_list + 5, mode->gain);
1012
1013 err = ov5650_write_table(info, reset_seq, NULL, 0);
1014 if (err)
1015 return err;
1016
1017 err = ov5650_write_table(info, mode_start, NULL, 0);
1018 if (err)
1019 return err;
1020
1021 err = ov5650_write_table(info, mode_table[sensor_mode],
1022 reg_list, 6);
1023 if (err)
1024 return err;
1025
1026 err = ov5650_write_table(info, mode_end, NULL, 0);
1027 if (err)
1028 return err;
1029
1030 info->mode = sensor_mode;
1031 return 0;
1032}
1033
1034static int ov5650_set_frame_length(struct ov5650_info *info, u32 frame_length)
1035{
1036 int ret;
1037 struct ov5650_reg reg_list[2];
1038 u8 *b_ptr = info->i2c_trans_buf;
1039
1040 ov5650_get_frame_length_regs(reg_list, frame_length);
1041
1042 *b_ptr++ = reg_list[0].addr >> 8;
1043 *b_ptr++ = reg_list[0].addr & 0xff;
1044 *b_ptr++ = reg_list[0].val & 0xff;
1045 *b_ptr++ = reg_list[1].val & 0xff;
1046 ret = ov5650_write_bulk_reg_helper(info, 4);
1047
1048 return ret;
1049}
1050
1051static int ov5650_set_coarse_time(struct ov5650_info *info, u32 coarse_time)
1052{
1053 int ret;
1054 struct ov5650_reg reg_list[3];
1055 u8 *b_ptr = info->i2c_trans_buf;
1056
1057 ov5650_get_coarse_time_regs(reg_list, coarse_time);
1058
1059 *b_ptr++ = reg_list[0].addr >> 8;
1060 *b_ptr++ = reg_list[0].addr & 0xff;
1061 *b_ptr++ = reg_list[0].val & 0xff;
1062 *b_ptr++ = reg_list[1].val & 0xff;
1063 *b_ptr++ = reg_list[2].val & 0xff;
1064 ret = ov5650_write_bulk_reg_helper(info, 5);
1065
1066 return ret;
1067}
1068
1069static int ov5650_set_gain(struct ov5650_info *info, u16 gain)
1070{
1071 int ret;
1072 struct ov5650_reg reg_list;
1073
1074 ov5650_get_gain_reg(&reg_list, gain);
1075 ret = ov5650_write_reg_helper(info, reg_list.addr, reg_list.val);
1076
1077 return ret;
1078}
1079
1080static int ov5650_set_group_hold(struct ov5650_info *info, struct ov5650_ae *ae)
1081{
1082 int ret;
1083 int count = 0;
1084 bool groupHoldEnabled = false;
1085
1086 if (ae->gain_enable)
1087 count++;
1088 if (ae->coarse_time_enable)
1089 count++;
1090 if (ae->frame_length_enable)
1091 count++;
1092 if (count >= 2)
1093 groupHoldEnabled = true;
1094
1095 if (groupHoldEnabled) {
1096 ret = ov5650_write_reg_helper(info, 0x3212, 0x01);
1097 if (ret)
1098 return ret;
1099 }
1100
1101 if (ae->gain_enable)
1102 ov5650_set_gain(info, ae->gain);
1103 if (ae->coarse_time_enable)
1104 ov5650_set_coarse_time(info, ae->coarse_time);
1105 if (ae->frame_length_enable)
1106 ov5650_set_frame_length(info, ae->frame_length);
1107
1108 if (groupHoldEnabled) {
1109 ret = ov5650_write_reg_helper(info, 0x3212, 0x11);
1110 if (ret)
1111 return ret;
1112
1113 ret = ov5650_write_reg_helper(info, 0x3212, 0xa1);
1114 if (ret)
1115 return ret;
1116 }
1117
1118 return 0;
1119}
1120
1121
1122static int ov5650_set_binning(struct ov5650_info *info, u8 enable)
1123{
1124 s32 ret;
1125 u8 array_ctrl_reg, analog_ctrl_reg, timing_reg;
1126 u32 val;
1127
1128 if (info->mode == OV5650_MODE_2592x1944
1129 || info->mode == OV5650_MODE_2080x1164
1130 || info->mode >= OV5650_MODE_INVALID) {
1131 return -EINVAL;
1132 }
1133
1134 ov5650_read_reg_helper(info, OV5650_ARRAY_CONTROL_01, &array_ctrl_reg);
1135 ov5650_read_reg_helper(info, OV5650_ANALOG_CONTROL_D, &analog_ctrl_reg);
1136 ov5650_read_reg_helper(info, OV5650_TIMING_TC_REG_18, &timing_reg);
1137
1138 ret = ov5650_write_reg_helper(info,
1139 OV5650_SRM_GRUP_ACCESS,
1140 OV5650_GROUP_ID(3));
1141 if (ret < 0)
1142 return -EIO;
1143
1144 if (!enable) {
1145 ret = ov5650_write_reg_helper(info,
1146 OV5650_ARRAY_CONTROL_01,
1147 array_ctrl_reg |
1148 (OV5650_H_BINNING_BIT | OV5650_H_SUBSAMPLING_BIT));
1149
1150 if (ret < 0)
1151 goto exit;
1152
1153 ret = ov5650_write_reg_helper(info,
1154 OV5650_ANALOG_CONTROL_D,
1155 analog_ctrl_reg & ~OV5650_V_BINNING_BIT);
1156
1157 if (ret < 0)
1158 goto exit;
1159
1160 ret = ov5650_write_reg_helper(info,
1161 OV5650_TIMING_TC_REG_18,
1162 timing_reg | OV5650_V_SUBSAMPLING_BIT);
1163
1164 if (ret < 0)
1165 goto exit;
1166
1167 if (info->mode == OV5650_MODE_1296x972)
1168 val = 0x1A2;
1169 else
1170 /* FIXME: this value is not verified yet. */
1171 val = 0x1A8;
1172
1173 ret = ov5650_write_reg_helper(info,
1174 OV5650_TIMING_CONTROL_HS_HIGH,
1175 (val >> 8));
1176
1177 if (ret < 0)
1178 goto exit;
1179
1180 ret = ov5650_write_reg_helper(info,
1181 OV5650_TIMING_CONTROL_HS_LOW,
1182 (val & 0xFF));
1183 } else {
1184 ret = ov5650_write_reg_helper(info,
1185 OV5650_ARRAY_CONTROL_01,
1186 (array_ctrl_reg | OV5650_H_BINNING_BIT)
1187 & ~OV5650_H_SUBSAMPLING_BIT);
1188
1189 if (ret < 0)
1190 goto exit;
1191
1192 ret = ov5650_write_reg_helper(info,
1193 OV5650_ANALOG_CONTROL_D,
1194 analog_ctrl_reg | OV5650_V_BINNING_BIT);
1195
1196 if (ret < 0)
1197 goto exit;
1198
1199 ret = ov5650_write_reg_helper(info,
1200 OV5650_TIMING_TC_REG_18,
1201 timing_reg | OV5650_V_SUBSAMPLING_BIT);
1202
1203 if (ret < 0)
1204 goto exit;
1205
1206 if (info->mode == OV5650_MODE_1296x972)
1207 val = 0x33C;
1208 else
1209 val = 0x254;
1210
1211 ret = ov5650_write_reg_helper(info,
1212 OV5650_TIMING_CONTROL_HS_HIGH,
1213 (val >> 8));
1214
1215 if (ret < 0)
1216 goto exit;
1217
1218 ret = ov5650_write_reg_helper(info,
1219 OV5650_TIMING_CONTROL_HS_LOW,
1220 (val & 0xFF));
1221 }
1222
1223exit:
1224 ret = ov5650_write_reg_helper(info,
1225 OV5650_SRM_GRUP_ACCESS,
1226 (OV5650_GROUP_HOLD_END_BIT | OV5650_GROUP_ID(3)));
1227
1228 ret |= ov5650_write_reg_helper(info,
1229 OV5650_SRM_GRUP_ACCESS,
1230 (OV5650_GROUP_HOLD_BIT | OV5650_GROUP_LAUNCH_BIT |
1231 OV5650_GROUP_ID(3)));
1232
1233 return ret;
1234}
1235
1236static int ov5650_test_pattern(struct ov5650_info *info,
1237 enum ov5650_test_pattern pattern)
1238{
1239 if (pattern >= ARRAY_SIZE(test_pattern_modes))
1240 return -EINVAL;
1241
1242 return ov5650_write_table(info,
1243 test_pattern_modes[pattern],
1244 NULL, 0);
1245}
1246
1247static int set_power_helper(struct ov5650_platform_data *pdata,
1248 int powerLevel)
1249{
1250 if (pdata) {
1251 if (powerLevel && pdata->power_on)
1252 pdata->power_on();
1253 else if (pdata->power_off)
1254 pdata->power_off();
1255 }
1256 return 0;
1257}
1258
1259static int ov5650_set_power(int powerLevel)
1260{
1261 pr_info("%s: powerLevel=%d camera mode=%d\n", __func__, powerLevel,
1262 stereo_ov5650_info->camera_mode);
1263
1264 if (StereoCameraMode_Left & stereo_ov5650_info->camera_mode)
1265 set_power_helper(stereo_ov5650_info->left.pdata, powerLevel);
1266
1267 if (StereoCameraMode_Right & stereo_ov5650_info->camera_mode)
1268 set_power_helper(stereo_ov5650_info->right.pdata, powerLevel);
1269
1270 return 0;
1271}
1272
1273static long ov5650_ioctl(struct file *file,
1274 unsigned int cmd, unsigned long arg)
1275{
1276 int err;
1277 struct ov5650_info *info = file->private_data;
1278
1279 switch (cmd) {
1280 case OV5650_IOCTL_SET_CAMERA_MODE:
1281 {
1282 if (info->camera_mode != arg) {
1283 err = ov5650_set_power(0);
1284 if (err) {
1285 pr_info("%s %d\n", __func__, __LINE__);
1286 return err;
1287 }
1288 info->camera_mode = arg;
1289 err = ov5650_set_power(1);
1290 if (err)
1291 return err;
1292 }
1293 return 0;
1294 }
1295 case OV5650_IOCTL_SYNC_SENSORS:
1296 if (info->right.pdata->synchronize_sensors)
1297 info->right.pdata->synchronize_sensors();
1298 return 0;
1299 case OV5650_IOCTL_SET_MODE:
1300 {
1301 struct ov5650_mode mode;
1302 if (copy_from_user(&mode,
1303 (const void __user *)arg,
1304 sizeof(struct ov5650_mode))) {
1305 pr_info("%s %d\n", __func__, __LINE__);
1306 return -EFAULT;
1307 }
1308
1309 return ov5650_set_mode(info, &mode);
1310 }
1311 case OV5650_IOCTL_SET_FRAME_LENGTH:
1312 return ov5650_set_frame_length(info, (u32)arg);
1313 case OV5650_IOCTL_SET_COARSE_TIME:
1314 return ov5650_set_coarse_time(info, (u32)arg);
1315 case OV5650_IOCTL_SET_GAIN:
1316 return ov5650_set_gain(info, (u16)arg);
1317 case OV5650_IOCTL_SET_BINNING:
1318 return ov5650_set_binning(info, (u8)arg);
1319 case OV5650_IOCTL_GET_STATUS:
1320 {
1321 u16 status = 0;
1322 if (copy_to_user((void __user *)arg, &status,
1323 2)) {
1324 pr_info("%s %d\n", __func__, __LINE__);
1325 return -EFAULT;
1326 }
1327 return 0;
1328 }
1329 case OV5650_IOCTL_TEST_PATTERN:
1330 {
1331 err = ov5650_test_pattern(info, (enum ov5650_test_pattern) arg);
1332 if (err)
1333 pr_err("%s %d %d\n", __func__, __LINE__, err);
1334 return err;
1335 }
1336 case OV5650_IOCTL_SET_GROUP_HOLD:
1337 {
1338 struct ov5650_ae ae;
1339 if (copy_from_user(&ae,
1340 (const void __user *)arg,
1341 sizeof(struct ov5650_ae))) {
1342 pr_info("%s %d\n", __func__, __LINE__);
1343 return -EFAULT;
1344 }
1345 return ov5650_set_group_hold(info, &ae);
1346 }
1347 default:
1348 return -EINVAL;
1349 }
1350 return 0;
1351}
1352
1353static int ov5650_open(struct inode *inode, struct file *file)
1354{
1355 pr_info("%s\n", __func__);
1356 file->private_data = stereo_ov5650_info;
1357 ov5650_set_power(1);
1358 return 0;
1359}
1360
1361int ov5650_release(struct inode *inode, struct file *file)
1362{
1363 ov5650_set_power(0);
1364 file->private_data = NULL;
1365 return 0;
1366}
1367
1368
1369static const struct file_operations ov5650_fileops = {
1370 .owner = THIS_MODULE,
1371 .open = ov5650_open,
1372 .unlocked_ioctl = ov5650_ioctl,
1373 .release = ov5650_release,
1374};
1375
1376static struct miscdevice ov5650_device = {
1377 .minor = MISC_DYNAMIC_MINOR,
1378 .name = "ov5650",
1379 .fops = &ov5650_fileops,
1380};
1381
1382static int ov5650_probe_common(void)
1383{
1384 int err;
1385
1386 if (!stereo_ov5650_info) {
1387 stereo_ov5650_info = kzalloc(sizeof(struct ov5650_info),
1388 GFP_KERNEL);
1389 if (!stereo_ov5650_info) {
1390 pr_err("ov5650: Unable to allocate memory!\n");
1391 return -ENOMEM;
1392 }
1393
1394 err = misc_register(&ov5650_device);
1395 if (err) {
1396 pr_err("ov5650: Unable to register misc device!\n");
1397 kfree(stereo_ov5650_info);
1398 return err;
1399 }
1400 }
1401 return 0;
1402}
1403
1404static int ov5650_remove_common(struct i2c_client *client)
1405{
1406 if (stereo_ov5650_info->left.i2c_client ||
1407 stereo_ov5650_info->right.i2c_client)
1408 return 0;
1409
1410 misc_deregister(&ov5650_device);
1411 kfree(stereo_ov5650_info);
1412 stereo_ov5650_info = NULL;
1413
1414 return 0;
1415}
1416
1417static int left_ov5650_probe(struct i2c_client *client,
1418 const struct i2c_device_id *id)
1419{
1420 int err;
1421 pr_info("%s: probing sensor.\n", __func__);
1422
1423 err = ov5650_probe_common();
1424 if (err)
1425 return err;
1426
1427 stereo_ov5650_info->left.pdata = client->dev.platform_data;
1428 stereo_ov5650_info->left.i2c_client = client;
1429
1430 return 0;
1431}
1432
1433static int left_ov5650_remove(struct i2c_client *client)
1434{
1435 if (stereo_ov5650_info) {
1436 stereo_ov5650_info->left.i2c_client = NULL;
1437 ov5650_remove_common(client);
1438 }
1439 return 0;
1440}
1441
1442static const struct i2c_device_id left_ov5650_id[] = {
1443 { "ov5650", 0 },
1444 { "ov5650L", 0 },
1445 { },
1446};
1447
1448MODULE_DEVICE_TABLE(i2c, left_ov5650_id);
1449
1450static struct i2c_driver left_ov5650_i2c_driver = {
1451 .driver = {
1452 .name = "ov5650",
1453 .owner = THIS_MODULE,
1454 },
1455 .probe = left_ov5650_probe,
1456 .remove = left_ov5650_remove,
1457 .id_table = left_ov5650_id,
1458};
1459
1460static int right_ov5650_probe(struct i2c_client *client,
1461 const struct i2c_device_id *id)
1462{
1463 int err;
1464 pr_info("%s: probing sensor.\n", __func__);
1465
1466 err = ov5650_probe_common();
1467 if (err)
1468 return err;
1469
1470 stereo_ov5650_info->right.pdata = client->dev.platform_data;
1471 stereo_ov5650_info->right.i2c_client = client;
1472
1473 return 0;
1474}
1475
1476static int right_ov5650_remove(struct i2c_client *client)
1477{
1478 if (stereo_ov5650_info) {
1479 stereo_ov5650_info->right.i2c_client = NULL;
1480 ov5650_remove_common(client);
1481 }
1482 return 0;
1483}
1484
1485static const struct i2c_device_id right_ov5650_id[] = {
1486 { "ov5650R", 0 },
1487 { },
1488};
1489
1490MODULE_DEVICE_TABLE(i2c, right_ov5650_id);
1491
1492static struct i2c_driver right_ov5650_i2c_driver = {
1493 .driver = {
1494 .name = "ov5650R",
1495 .owner = THIS_MODULE,
1496 },
1497 .probe = right_ov5650_probe,
1498 .remove = right_ov5650_remove,
1499 .id_table = right_ov5650_id,
1500};
1501
1502static int __init ov5650_init(void)
1503{
1504 int ret;
1505 pr_info("ov5650 sensor driver loading\n");
1506 ret = i2c_add_driver(&left_ov5650_i2c_driver);
1507 if (ret)
1508 return ret;
1509 return i2c_add_driver(&right_ov5650_i2c_driver);
1510}
1511
1512static void __exit ov5650_exit(void)
1513{
1514 i2c_del_driver(&right_ov5650_i2c_driver);
1515 i2c_del_driver(&left_ov5650_i2c_driver);
1516}
1517
1518module_init(ov5650_init);
1519module_exit(ov5650_exit);
1520
diff --git a/drivers/media/video/tegra/ov9726.c b/drivers/media/video/tegra/ov9726.c
new file mode 100644
index 00000000000..655d07c736a
--- /dev/null
+++ b/drivers/media/video/tegra/ov9726.c
@@ -0,0 +1,845 @@
1/*
2 * ov9726.c - ov9726 sensor driver
3 *
4 * Copyright (c) 2011, NVIDIA, All Rights Reserved.
5 *
6 * Contributors:
7 * Charlie Huang <chahuang@nvidia.com>
8 *
9 * This file is licensed under the terms of the GNU General Public License
10 * version 2. This program is licensed "as is" without any warranty of any
11 * kind, whether express or implied.
12 */
13
14#include <linux/kernel.h>
15#include <linux/delay.h>
16#include <linux/fs.h>
17#include <linux/i2c.h>
18#include <linux/miscdevice.h>
19#include <linux/slab.h>
20#include <linux/io.h>
21#include <linux/uaccess.h>
22#include <mach/iomap.h>
23#include <linux/atomic.h>
24#include <mach/gpio.h>
25#include <linux/regulator/consumer.h>
26
27#include <media/ov9726.h>
28
29struct ov9726_power_rail {
30 struct regulator *sen_1v8_reg;
31 struct regulator *sen_2v8_reg;
32};
33
34struct ov9726_devinfo {
35 struct miscdevice miscdev_info;
36 struct i2c_client *i2c_client;
37 struct ov9726_platform_data *pdata;
38 struct ov9726_power_rail power_rail;
39 atomic_t in_use;
40 __u32 mode;
41};
42
43static struct ov9726_reg mode_1280x720[] = {
44 /*
45 (1) clock setting
46 clock formula: (Ref_clk / pre_pll_clk_div) * pll_multiplier /
47 vt_sys_clk_div / vt_pix_clk_div / divmip
48 input clk at 24Mhz
49 pre_pll_clk_div 0305[3:0] => 4
50 pll_multiplier 0307[6:0] => 100
51 vt_sys_clk_div 0303[3:0] => 1
52 vt_pix_clk_div 0301[3:0] => 10
53 divmip 3010[2:0] => 1
54
55 Overall timing:
56 line length: 1664 (reg 0x342/0x343)
57 frame length: 840 (reg 0x340/0x341)
58 coarse integration time: 835 lines (reg 0x202/0x203) => change to 836
59
60 visible pixels: (0,40) - (1280, 720+40) with size 1280x720
61 Output pixels (1280x720)
62
63 Frame rate if MCLK=24MHz:
64 24Mhz/4 *100/1/10/1 = 60 Mhz
65 60Mhz/1664/840 = 42.9 fps
66 */
67
68 {0x0103, 0x01},
69
70 {OV9726_TABLE_WAIT_MS, 10},
71
72 {0x3026, 0x00},
73 {0x3027, 0x00},
74 {0x3705, 0x45},
75 {0x3603, 0xaa},
76 {0x3632, 0x2f},
77 {0x3620, 0x66},
78 {0x3621, 0xc0},
79 {0x0202, 0x03},
80 {0x0203, 0x13},
81 {0x3833, 0x04},
82 {0x3835, 0x02},
83 {0x4702, 0x04},
84 {0x4704, 0x00},
85 {0x4706, 0x08},
86 {0x5052, 0x01},
87 {0x3819, 0x6c},
88 {0x3817, 0x94},
89 {0x404e, 0x7e},
90 {0x3601, 0x40},
91 {0x3610, 0xa0},
92 {0x0344, 0x00},
93 {0x0345, 0x00},
94 {0x0346, 0x00},
95 {0x0347, 0x28},
96
97 {0x034c, 0x05},
98 {0x034d, 0x00},
99 {0x034e, 0x02},
100 {0x034f, 0xd8},
101 {0x3002, 0x00},
102 {0x3004, 0x00},
103 {0x3005, 0x00},
104 {0x4800, 0x44},
105 {0x4801, 0x0f},
106 {0x4803, 0x05},
107 {0x4601, 0x16},
108 {0x3014, 0x05},
109 {0x0101, 0x01},
110 {0x3707, 0x14},
111 {0x3622, 0x9f},
112 {0x4002, 0x45},
113 {0x5001, 0x00},
114 {0x3406, 0x01},
115 {0x3503, 0x17},
116 {0x0205, 0x3f},
117 {0x0100, 0x01},
118 {0x0112, 0x0a},
119 {0x0113, 0x0a},
120 {0x3013, 0x20},
121 {0x4837, 0x2f},
122 {0x3615, 0xf0},
123 {0x0340, 0x03},
124 {0x0341, 0x48},
125 {0x0342, 0x06},
126 {0x0343, 0x80},
127 {0x3702, 0x1e},
128 {0x3703, 0x3c},
129 {0x3704, 0x0e},
130
131 {0x3104, 0x20},
132 {0x0305, 0x04},
133 {0x0307, 0x46},
134 {0x0303, 0x01},
135 {0x0301, 0x0a},
136 {0x3010, 0x01},
137 {0x460e, 0x00},
138
139 {0x5000, 0x00},
140 {0x5002, 0x00},
141 {0x3017, 0xd2},
142 {0x3018, 0x69},
143 {0x3019, 0x96},
144 {0x5047, 0x61},
145 {0x3604, 0x1c},
146 {0x3602, 0x10},
147 {0x3612, 0x21},
148 {0x3630, 0x0a},
149 {0x3631, 0x53},
150 {0x3633, 0x70},
151 {0x4005, 0x1a},
152 {0x4009, 0x10},
153
154 {OV9726_TABLE_END, 0x0000}
155};
156
157static struct ov9726_reg mode_1280x800[] = {
158 {0x0103, 0x01},
159
160 {OV9726_TABLE_WAIT_MS, 10},
161
162 {0x3026, 0x00},
163 {0x3027, 0x00},
164 {0x3705, 0x45},
165 {0x3603, 0xaa},
166 {0x3632, 0x2f},
167 {0x3620, 0x66},
168 {0x3621, 0xc0},
169 {0x0202, 0x03},
170 {0x0203, 0x13},
171 {0x3833, 0x04},
172 {0x3835, 0x02},
173 {0x4702, 0x04},
174 {0x4704, 0x00},
175 {0x4706, 0x08},
176 {0x5052, 0x01},
177 {0x3819, 0x6c},
178 {0x3817, 0x94},
179 {0x404e, 0x7e},
180 {0x3601, 0x40},
181 {0x3610, 0xa0},
182
183 {0x0344, 0x00},
184 {0x0345, 0x00},
185 {0x0346, 0x00},
186 {0x0347, 0x00},
187 {0x034c, 0x05},
188 {0x034d, 0x10},
189 {0x034e, 0x03},
190 {0x034f, 0x28},
191
192 {0x3002, 0x00},
193 {0x3004, 0x00},
194 {0x3005, 0x00},
195 {0x4800, 0x44},
196 {0x4801, 0x0f},
197 {0x4803, 0x05},
198 {0x4601, 0x16},
199 {0x3014, 0x05},
200 {0x0101, 0x01},
201 {0x3707, 0x14},
202 {0x3622, 0x9f},
203 {0x4002, 0x45},
204 {0x5001, 0x00},
205 {0x3406, 0x01},
206 {0x3503, 0x17},
207 {0x0205, 0x3f},
208 {0x0100, 0x01},
209 {0x0112, 0x0a},
210 {0x0113, 0x0a},
211 {0x3013, 0x20},
212 {0x4837, 0x2f},
213 {0x3615, 0xf0},
214 {0x0340, 0x03},
215 {0x0341, 0x48},
216 {0x0342, 0x06},
217 {0x0343, 0x80},
218 {0x3702, 0x1e},
219 {0x3703, 0x3c},
220 {0x3704, 0x0e},
221
222 {0x3104, 0x20},
223 {0x0305, 0x04},
224 {0x0307, 0x46},
225 {0x0303, 0x01},
226 {0x0301, 0x0a},
227 {0x3010, 0x01},
228 {0x460e, 0x00},
229
230 {0x5000, 0x00},
231 {0x5002, 0x00},
232 {0x3017, 0xd2},
233 {0x3018, 0x69},
234 {0x3019, 0x96},
235 {0x5047, 0x61},
236 {0x3604, 0x1c},
237 {0x3602, 0x10},
238 {0x3612, 0x21},
239 {0x3630, 0x0a},
240 {0x3631, 0x53},
241 {0x3633, 0x70},
242 {0x4005, 0x1a},
243 {0x4009, 0x10},
244
245 {OV9726_TABLE_END, 0x0000}
246};
247
248enum {
249 OV9726_MODE_1280x720,
250 OV9726_MODE_1280x800,
251};
252
253static struct ov9726_reg *mode_table[] = {
254 [OV9726_MODE_1280x720] = mode_1280x720,
255 [OV9726_MODE_1280x800] = mode_1280x800,
256};
257
258static inline void
259msleep_range(unsigned int delay_base)
260{
261 usleep_range(delay_base*1000, delay_base*1000 + 500);
262}
263
264static inline int
265ov9726_power_init(struct ov9726_devinfo *dev)
266{
267 struct i2c_client *i2c_client = dev->i2c_client;
268 int err = 0;
269
270 dev->power_rail.sen_1v8_reg = regulator_get(&i2c_client->dev, "dovdd");
271 if (IS_ERR_OR_NULL(dev->power_rail.sen_1v8_reg)) {
272 dev_err(&i2c_client->dev, "%s: failed to get vdd\n",
273 __func__);
274 err = PTR_ERR(dev->power_rail.sen_1v8_reg);
275 goto ov9726_power_init_end;
276 }
277
278 dev->power_rail.sen_2v8_reg = regulator_get(&i2c_client->dev, "avdd");
279 if (IS_ERR_OR_NULL(dev->power_rail.sen_2v8_reg)) {
280 dev_err(&i2c_client->dev, "%s: failed to get vaa\n",
281 __func__);
282 err = PTR_ERR(dev->power_rail.sen_2v8_reg);
283
284 regulator_put(dev->power_rail.sen_1v8_reg);
285 dev->power_rail.sen_1v8_reg = NULL;
286 }
287
288ov9726_power_init_end:
289 return err;
290}
291
292static inline void
293ov9726_power_release(struct ov9726_devinfo *dev)
294{
295 regulator_put(dev->power_rail.sen_1v8_reg);
296 regulator_put(dev->power_rail.sen_2v8_reg);
297}
298
299static int
300ov9726_power(struct ov9726_devinfo *dev, bool pwr_on)
301{
302 struct i2c_client *i2c_client = dev->i2c_client;
303 int rst_active_state = dev->pdata->rst_low_active ? 0 : 1;
304 int pwdn_active_state = dev->pdata->pwdn_low_active ? 0 : 1;
305 int ret = 0;
306
307 dev_info(&i2c_client->dev, "%s %s\n", __func__, pwr_on ? "on" : "off");
308
309 if (pwr_on) {
310 /* pull low the RST pin of ov9726 first */
311 gpio_set_value(dev->pdata->gpio_rst, rst_active_state);
312 msleep_range(1);
313 /* Plug 1.8V and 2.8V power to sensor */
314 ret = regulator_enable(dev->power_rail.sen_1v8_reg);
315 if (ret) {
316 dev_err(&i2c_client->dev, "%s: failed to enable vdd\n",
317 __func__);
318 goto fail_regulator_1v8_reg;
319 }
320
321 msleep_range(20);
322
323 ret = regulator_enable(dev->power_rail.sen_2v8_reg);
324 if (ret) {
325 dev_err(&i2c_client->dev, "%s: failed to enable vaa\n",
326 __func__);
327 goto fail_regulator_2v8_reg;
328 }
329 msleep_range(1);
330 /* turn on ov9726 */
331 gpio_set_value(dev->pdata->gpio_pwdn, !pwdn_active_state);
332
333 msleep_range(5);
334 /* release RST pin */
335 gpio_set_value(dev->pdata->gpio_rst, !rst_active_state);
336 msleep_range(20);
337
338 /* Board specific power-on sequence */
339 dev->pdata->power_on();
340 } else {
341 /* pull low the RST pin of ov9726 */
342 gpio_set_value(dev->pdata->gpio_rst, rst_active_state);
343 msleep_range(1);
344 /* turn off ov9726 */
345 gpio_set_value(dev->pdata->gpio_pwdn, pwdn_active_state);
346 msleep_range(1);
347
348 /* Unplug 1.8V and 2.8V power from sensor */
349 regulator_disable(dev->power_rail.sen_2v8_reg);
350 regulator_disable(dev->power_rail.sen_1v8_reg);
351
352 /* Board specific power-down sequence */
353 dev->pdata->power_off();
354 }
355
356 return 0;
357
358fail_regulator_2v8_reg:
359 regulator_put(dev->power_rail.sen_2v8_reg);
360 dev->power_rail.sen_2v8_reg = NULL;
361 regulator_disable(dev->power_rail.sen_1v8_reg);
362fail_regulator_1v8_reg:
363 regulator_put(dev->power_rail.sen_1v8_reg);
364 dev->power_rail.sen_1v8_reg = NULL;
365 return ret;
366}
367
368static inline void
369ov9726_get_frame_length_regs(struct ov9726_reg *regs, u32 frame_length)
370{
371 regs->addr = OV9726_REG_FRAME_LENGTH_HI;
372 regs->val = (frame_length >> 8) & 0xff;
373 regs++;
374 regs->addr = OV9726_REG_FRAME_LENGTH_LO;
375 regs->val = frame_length & 0xff;
376}
377
378static inline void
379ov9726_get_coarse_time_regs(struct ov9726_reg *regs, u32 coarse_time)
380{
381 regs->addr = OV9726_REG_COARSE_TIME_HI;
382 regs->val = (coarse_time >> 8) & 0xff;
383 regs++;
384 regs->addr = OV9726_REG_COARSE_TIME_LO;
385 regs->val = coarse_time & 0xff;
386}
387
388static inline void
389ov9726_get_gain_reg(struct ov9726_reg *regs, u16 gain)
390{
391 regs->addr = OV9726_REG_GAIN_HI;
392 regs->val = (gain >> 8) & 0xff;
393 regs++;
394 regs->addr = OV9726_REG_GAIN_LO;
395 regs->val = gain & 0xff;
396}
397
398static int
399ov9726_read_reg8(struct i2c_client *client, u16 addr, u8 *val)
400{
401 int err;
402 struct i2c_msg msg[2];
403 unsigned char data[3];
404
405 if (!client->adapter)
406 return -ENODEV;
407
408 msg[0].addr = client->addr;
409 msg[0].flags = 0;
410 msg[0].len = 2;
411 msg[0].buf = data;
412
413 /* high byte goes out first */
414 data[0] = (u8)(addr >> 8);
415 data[1] = (u8)(addr & 0xff);
416
417 msg[1].addr = client->addr;
418 msg[1].flags = I2C_M_RD;
419 msg[1].len = 1;
420 msg[1].buf = data + 2;
421
422 err = i2c_transfer(client->adapter, msg, 2);
423
424 if (err != 2)
425 err = -EINVAL;
426 else {
427 *val = data[2];
428 err = 0;
429 }
430
431 return err;
432}
433
434static int
435ov9726_write_reg8(struct i2c_client *client, u16 addr, u8 val)
436{
437 int err;
438 struct i2c_msg msg;
439 unsigned char data[3];
440 int retry = 0;
441
442 if (!client->adapter)
443 return -ENODEV;
444
445 data[0] = (u8)(addr >> 8);
446 data[1] = (u8)(addr & 0xff);
447 data[2] = (u8)(val & 0xff);
448
449 msg.addr = client->addr;
450 msg.flags = 0;
451 msg.len = 3;
452 msg.buf = data;
453
454 do {
455 err = i2c_transfer(client->adapter, &msg, 1);
456 if (err == 1)
457 break;
458
459 retry++;
460 dev_err(&client->dev,
461 "ov9726: i2c transfer failed, retrying %x %x\n",
462 addr, val);
463 msleep_range(3);
464 } while (retry <= OV9726_MAX_RETRIES);
465
466 return (err != 1);
467}
468
469static int
470ov9726_write_reg16(struct i2c_client *client, u16 addr, u16 val)
471{
472 int count;
473 struct i2c_msg msg;
474 unsigned char data[4];
475 int retry = 0;
476
477 if (!client->adapter)
478 return -ENODEV;
479
480 data[0] = (u8)(addr >> 8);
481 data[1] = (u8)(addr & 0xff);
482 data[2] = (u8)(val >> 8);
483 data[3] = (u8)(val & 0xff);
484
485 msg.addr = client->addr;
486 msg.flags = 0;
487 msg.len = 4;
488 msg.buf = data;
489
490 do {
491 count = i2c_transfer(client->adapter, &msg, 1);
492 if (count == 1)
493 return 0;
494
495 retry++;
496 dev_err(&client->dev,
497 "ov9726: i2c transfer failed, retrying %x %x %x\n",
498 addr, val, count);
499 msleep_range(3);
500 } while (retry <= OV9726_MAX_RETRIES);
501
502 return -EIO;
503}
504
505static int
506ov9726_write_table(
507 struct i2c_client *client,
508 struct ov9726_reg table[],
509 struct ov9726_reg override_list[],
510 int num_override_regs)
511{
512 const struct ov9726_reg *next;
513 int err = 0;
514 int i;
515 u16 val;
516
517 dev_info(&client->dev, "ov9726_write_table\n");
518
519 for (next = table; next->addr != OV9726_TABLE_END; next++) {
520
521 if (next->addr == OV9726_TABLE_WAIT_MS) {
522 msleep_range(next->val);
523 continue;
524 }
525
526 val = next->val;
527
528 /* When an override list is passed in, replace the reg */
529 /* value to write if the reg is in the list */
530 if (override_list) {
531 for (i = 0; i < num_override_regs; i++) {
532 if (next->addr == override_list[i].addr) {
533 val = override_list[i].val;
534 break;
535 }
536 }
537 }
538
539 err = ov9726_write_reg8(client, next->addr, val);
540 if (err)
541 break;
542 }
543
544 return err;
545}
546
547static int
548ov9726_set_frame_length(struct i2c_client *i2c_client, u32 frame_length)
549{
550 int ret;
551
552 dev_info(&i2c_client->dev, "[%s] (0x%08x)\n", __func__, frame_length);
553 /* hold register value */
554 ret = ov9726_write_reg8(i2c_client, 0x104, 0x01);
555 if (ret)
556 return ret;
557
558 ret = ov9726_write_reg16(i2c_client,
559 OV9726_REG_FRAME_LENGTH_HI,
560 frame_length);
561
562 /* release hold, update register value */
563 ret |= ov9726_write_reg8(i2c_client, 0x104, 0x00);
564
565 return ret;
566}
567
568static int
569ov9726_set_coarse_time(struct i2c_client *i2c_client, u32 coarse_time)
570{
571 int ret;
572
573 dev_info(&i2c_client->dev, "[%s] (0x%08x)\n", __func__, coarse_time);
574 /* hold register value */
575 ret = ov9726_write_reg8(i2c_client, 0x104, 0x01);
576 if (ret)
577 return ret;
578
579 ret = ov9726_write_reg16(i2c_client,
580 OV9726_REG_COARSE_TIME_HI,
581 coarse_time);
582
583 /* release hold, update register value */
584 ret |= ov9726_write_reg8(i2c_client, 0x104, 0x00);
585
586 return ret;
587}
588
589static int ov9726_set_gain(struct i2c_client *i2c_client, u16 gain)
590{
591 int ret;
592
593 /* hold register value */
594 ret = ov9726_write_reg8(i2c_client, 0x104, 0x01);
595 if (ret)
596 return ret;
597
598 ret = ov9726_write_reg16(i2c_client, OV9726_REG_GAIN_HI, gain);
599
600 /* release hold, update register value */
601 ret |= ov9726_write_reg8(i2c_client, 0x104, 0x00);
602
603 return ret;
604}
605
606static int ov9726_get_status(struct i2c_client *i2c_client, u8 *status)
607{
608 int err;
609
610 err = ov9726_read_reg8(i2c_client, 0x003, status);
611 *status = 0;
612 return err;
613}
614
615static int
616ov9726_set_mode(
617 struct ov9726_devinfo *dev,
618 struct ov9726_mode *mode)
619{
620 struct i2c_client *i2c_client = dev->i2c_client;
621 struct ov9726_reg reg_override[6];
622 int err = 0;
623 int sensor_mode;
624
625 dev_info(&i2c_client->dev, "%s.\n", __func__);
626
627 if (mode->xres == 1280 && mode->yres == 800)
628 sensor_mode = OV9726_MODE_1280x800;
629 else if (mode->xres == 1280 && mode->yres == 720)
630 sensor_mode = OV9726_MODE_1280x720;
631 else {
632 dev_err(&i2c_client->dev,
633 "%s: invalid resolution supplied to set mode %d %d\n",
634 __func__, mode->xres, mode->yres);
635 return -EINVAL;
636 }
637
638 ov9726_get_frame_length_regs(reg_override, mode->frame_length);
639 ov9726_get_coarse_time_regs(reg_override + 2, mode->coarse_time);
640 ov9726_get_gain_reg(reg_override + 4, mode->gain);
641
642 if (dev->mode != mode->mode_id) {
643 dev_info(&i2c_client->dev,
644 "%s: xres %u yres %u framelen %u coarse %u gain %u\n",
645 __func__, mode->xres, mode->yres, mode->frame_length,
646 mode->coarse_time, mode->gain);
647
648 err = ov9726_write_table(i2c_client,
649 mode_table[sensor_mode], reg_override,
650 sizeof(reg_override) / sizeof(reg_override[0]));
651 if (err)
652 goto ov9726_set_mode_exit;
653
654 dev->mode = mode->mode_id;
655 }
656
657ov9726_set_mode_exit:
658 return err;
659}
660
661static long
662ov9726_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
663{
664 struct ov9726_devinfo *dev = file->private_data;
665 struct i2c_client *i2c_client = dev->i2c_client;
666 int err = 0;
667
668 switch (cmd) {
669 case OV9726_IOCTL_SET_MODE:
670 {
671 struct ov9726_mode mode;
672
673 if (copy_from_user(&mode,
674 (const void __user *)arg,
675 sizeof(struct ov9726_mode))) {
676 err = -EFAULT;
677 break;
678 }
679
680 err = ov9726_set_mode(dev, &mode);
681
682 break;
683 }
684
685 case OV9726_IOCTL_SET_FRAME_LENGTH:
686 err = ov9726_set_frame_length(i2c_client, (u32)arg);
687 break;
688
689 case OV9726_IOCTL_SET_COARSE_TIME:
690 err = ov9726_set_coarse_time(i2c_client, (u32)arg);
691 break;
692
693 case OV9726_IOCTL_SET_GAIN:
694 err = ov9726_set_gain(i2c_client, (u16)arg);
695 break;
696
697 case OV9726_IOCTL_GET_STATUS:
698 {
699 u8 status;
700
701 err = ov9726_get_status(i2c_client, &status);
702 if (!err) {
703 if (copy_to_user((void __user *)arg,
704 &status, sizeof(status)))
705 err = -EFAULT;
706 }
707 break;
708 }
709
710 default:
711 err = -EINVAL;
712 break;
713 }
714
715 return err;
716}
717
718static int ov9726_open(struct inode *inode, struct file *file)
719{
720 struct miscdevice *miscdev = file->private_data;
721 struct ov9726_devinfo *dev;
722
723 dev = container_of(miscdev, struct ov9726_devinfo, miscdev_info);
724 /* check if device is in use */
725 if (atomic_xchg(&dev->in_use, 1))
726 return -EBUSY;
727 dev->mode = (__u32)-1;
728 file->private_data = dev;
729
730 ov9726_power(dev, true);
731
732 return 0;
733}
734
735int ov9726_release(struct inode *inode, struct file *file)
736{
737 struct ov9726_devinfo *dev;
738
739 dev = file->private_data;
740 file->private_data = NULL;
741
742 ov9726_power(dev, false);
743
744 /* warn if device already released */
745 WARN_ON(!atomic_xchg(&dev->in_use, 0));
746 return 0;
747}
748
749static const struct file_operations ov9726_fileops = {
750 .owner = THIS_MODULE,
751 .open = ov9726_open,
752 .unlocked_ioctl = ov9726_ioctl,
753 .release = ov9726_release,
754};
755
756static struct miscdevice ov9726_device = {
757 .name = "ov9726",
758 .minor = MISC_DYNAMIC_MINOR,
759 .fops = &ov9726_fileops,
760};
761
762static int
763ov9726_probe(struct i2c_client *client, const struct i2c_device_id *id)
764{
765 struct ov9726_devinfo *dev;
766 int err = 0;
767
768 dev_info(&client->dev, "ov9726: probing sensor.\n");
769
770 dev = kzalloc(sizeof(struct ov9726_devinfo), GFP_KERNEL);
771 if (!dev) {
772 dev_err(&client->dev, "ov9726: Unable to allocate memory!\n");
773 err = -ENOMEM;
774 goto probe_end;
775 }
776
777 memcpy(&(dev->miscdev_info),
778 &ov9726_device,
779 sizeof(struct miscdevice));
780
781 err = misc_register(&(dev->miscdev_info));
782 if (err) {
783 dev_err(&client->dev, "ov9726: Unable to register misc device!\n");
784 goto probe_end;
785 }
786
787 dev->pdata = client->dev.platform_data;
788 dev->i2c_client = client;
789 atomic_set(&dev->in_use, 0);
790 i2c_set_clientdata(client, dev);
791
792 err = ov9726_power_init(dev);
793
794probe_end:
795 if (err) {
796 kfree(dev);
797 dev_err(&client->dev, "failed.\n");
798 }
799
800 return err;
801}
802
803static int ov9726_remove(struct i2c_client *client)
804{
805 struct ov9726_devinfo *dev;
806
807 dev = i2c_get_clientdata(client);
808 i2c_set_clientdata(client, NULL);
809 misc_deregister(&ov9726_device);
810 ov9726_power_release(dev);
811 kfree(dev);
812
813 return 0;
814}
815
816static const struct i2c_device_id ov9726_id[] = {
817 {"ov9726", 0},
818 {},
819};
820
821MODULE_DEVICE_TABLE(i2c, ov9726_id);
822
823static struct i2c_driver ov9726_i2c_driver = {
824 .driver = {
825 .name = "ov9726",
826 .owner = THIS_MODULE,
827 },
828 .probe = ov9726_probe,
829 .remove = ov9726_remove,
830 .id_table = ov9726_id,
831};
832
833static int __init ov9726_init(void)
834{
835 pr_info("ov9726 sensor driver loading\n");
836 return i2c_add_driver(&ov9726_i2c_driver);
837}
838
839static void __exit ov9726_exit(void)
840{
841 i2c_del_driver(&ov9726_i2c_driver);
842}
843
844module_init(ov9726_init);
845module_exit(ov9726_exit);
diff --git a/drivers/media/video/tegra/sh532u.c b/drivers/media/video/tegra/sh532u.c
new file mode 100644
index 00000000000..7db14fcf257
--- /dev/null
+++ b/drivers/media/video/tegra/sh532u.c
@@ -0,0 +1,1688 @@
1/*
2 * SH532U focuser driver.
3 *
4 * Copyright (C) 2011 NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 * 02111-1307, USA
19 */
20
21/* Implementation
22 * --------------
23 * The board level details about the device need to be provided in the board
24 * file with the sh532u_platform_data structure.
25 * Standard among NVC kernel drivers in this structure is:
26 * .cfg = Use the NVC_CFG_ defines that are in nvc.h.
27 * Descriptions of the configuration options are with the defines.
28 * This value is typically 0.
29 * .num = The number of the instance of the device. This should start at 1 and
30 * and increment for each device on the board. This number will be
31 * appended to the MISC driver name, Example: /dev/focuser.1
32 * If not used or 0, then nothing is appended to the name.
33 * .sync = If there is a need to synchronize two devices, then this value is
34 * the number of the device instance (.num above) this device is to
35 * sync to. For example:
36 * Device 1 platform entries =
37 * .num = 1,
38 * .sync = 2,
39 * Device 2 platfrom entries =
40 * .num = 2,
41 * .sync = 1,
42 * The above example sync's device 1 and 2.
43 * This is typically used for stereo applications.
44 * .dev_name = The MISC driver name the device registers as. If not used,
45 * then the part number of the device is used for the driver name.
46 * If using the NVC user driver then use the name found in this
47 * driver under _default_pdata.
48 *
49 * The following is specific to NVC kernel focus drivers:
50 * .nvc = Pointer to the nvc_focus_nvc structure. This structure needs to
51 * be defined and populated if overriding the driver defaults.
52 * .cap = Pointer to the nvc_focus_cap structure. This structure needs to
53 * be defined and populated if overriding the driver defaults.
54 *
55 * The following is specific to only this NVC kernel focus driver:
56 * .info = Pointer to the sh532u_pdata_info structure. This structure does
57 * not need to be defined and populated unless overriding ROM data.
58.* .i2c_addr_rom = The I2C address of the onboard ROM.
59 * .gpio_reset = The GPIO connected to the devices reset. If not used then
60 * leave blank.
61 * .gpio_en = Due to a Linux limitation, a GPIO is defined to "enable" the
62 * device. This workaround is for when the device's power GPIO's
63 * are behind an I2C expander. The Linux limitation doesn't allow
64 * the I2C GPIO expander to be ready for use when this device is
65 * probed. When this problem is solved, this driver needs to
66 * remove the gpio_en WAR.
67 *
68 * Power Requirements
69 * The board power file must contain the following labels for the power
70 * regulator(s) of this device:
71 * "vdd" = the power regulator for the device's power.
72 * "vdd_i2c" = the power regulator for the I2C power.
73 *
74 * The above values should be all that is needed to use the device with this
75 * driver. Modifications of this driver should not be needed.
76 */
77
78
79#include <linux/fs.h>
80#include <linux/i2c.h>
81#include <linux/miscdevice.h>
82#include <linux/slab.h>
83#include <linux/delay.h>
84#include <linux/uaccess.h>
85#include <linux/list.h>
86#include <linux/jiffies.h>
87#include <linux/gpio.h>
88#include <media/nvc.h>
89#include <media/sh532u.h>
90
91#define SH532U_ID 0xF0
92/* defaults if no ROM data */
93#define SH532U_HYPERFOCAL_RATIO 1836 /* 41.2f/224.4f Ratio source: SEMCO */
94/* _HYPERFOCAL_RATIO is multiplied and _HYPERFOCAL_DIV divides for float */
95#define SH532U_HYPERFOCAL_DIV 10000
96#define SH532U_FOCAL_LENGTH 0x408D70A4
97#define SH532U_FNUMBER 0x40333333
98#define SH532U_MAX_APERATURE 0x3FCA0EA1
99/* SH532U_CAPS_VER = 0: invalid value */
100/* SH532U_CAPS_VER = 1: added NVC_PARAM_STS */
101/* SH532U_CAPS_VER = 2: expanded nvc_focus_cap */
102#define SH532U_CAPS_VER 2
103#define SH532U_ACTUATOR_RANGE 1000
104#define SH532U_SETTLETIME 30
105#define SH532U_FOCUS_MACRO 950
106#define SH532U_FOCUS_HYPER 250
107#define SH532U_FOCUS_INFINITY 50
108#define SH532U_TIMEOUT_MS 200
109#define SH532U_POS_LOW_DEFAULT 0xA000
110#define SH532U_POS_HIGH_DEFAULT 0x6000
111
112
113struct sh532u_info {
114 atomic_t in_use;
115 struct i2c_client *i2c_client;
116 struct sh532u_platform_data *pdata;
117 struct miscdevice miscdev;
118 struct list_head list;
119 int pwr_api;
120 int pwr_dev;
121 struct nvc_regulator vreg_vdd;
122 struct nvc_regulator vreg_i2c;
123 u8 s_mode;
124 struct sh532u_info *s_info;
125 unsigned i2c_addr_rom;
126 struct nvc_focus_nvc nvc;
127 struct nvc_focus_cap cap;
128 enum nvc_focus_sts sts;
129 struct sh532u_pdata_info cfg;
130 bool gpio_flag_reset;
131 bool init_cal_flag;
132 s16 abs_base;
133 u32 abs_range;
134 u32 pos_rel;
135 s16 pos_abs;
136 long pos_time_wr;
137};
138
139static struct sh532u_pdata_info sh532u_default_info = {
140 .move_timeoutms = SH532U_TIMEOUT_MS,
141 .focus_hyper_ratio = SH532U_HYPERFOCAL_RATIO,
142 .focus_hyper_div = SH532U_HYPERFOCAL_DIV,
143};
144
145static struct nvc_focus_cap sh532u_default_cap = {
146 .version = SH532U_CAPS_VER,
147 .actuator_range = SH532U_ACTUATOR_RANGE,
148 .settle_time = SH532U_SETTLETIME,
149 .focus_macro = SH532U_FOCUS_MACRO,
150 .focus_hyper = SH532U_FOCUS_HYPER,
151 .focus_infinity = SH532U_FOCUS_INFINITY,
152};
153
154static struct nvc_focus_nvc sh532u_default_nvc = {
155 .focal_length = SH532U_FOCAL_LENGTH,
156 .fnumber = SH532U_FNUMBER,
157 .max_aperature = SH532U_MAX_APERATURE,
158};
159
160static struct sh532u_platform_data sh532u_default_pdata = {
161 .cfg = 0,
162 .num = 0,
163 .sync = 0,
164 .dev_name = "focuser",
165 .i2c_addr_rom = 0x50,
166};
167
168static u32 sh532u_a2buf[] = {
169 0x0018019c,
170 0x0018019d,
171 0x0000019e,
172 0x007f0192,
173 0x00000194,
174 0x00f00184,
175 0x00850187,
176 0x0000018a,
177 0x00fd7187,
178 0x007f7183,
179 0x0008025a,
180 0x05042218,
181 0x80010216,
182 0x000601a0,
183 0x00808183,
184 0xffffffff
185};
186
187static LIST_HEAD(sh532u_info_list);
188static DEFINE_SPINLOCK(sh532u_spinlock);
189
190
191static int sh532u_i2c_rd8(struct sh532u_info *info, u8 addr, u8 reg, u8 *val)
192{
193 struct i2c_msg msg[2];
194 u8 buf[2];
195
196 buf[0] = reg;
197 if (addr) {
198 msg[0].addr = addr;
199 msg[1].addr = addr;
200 } else {
201 msg[0].addr = info->i2c_client->addr;
202 msg[1].addr = info->i2c_client->addr;
203 }
204 msg[0].flags = 0;
205 msg[0].len = 1;
206 msg[0].buf = &buf[0];
207 msg[1].flags = I2C_M_RD;
208 msg[1].len = 1;
209 msg[1].buf = &buf[1];
210 *val = 0;
211 if (i2c_transfer(info->i2c_client->adapter, msg, 2) != 2)
212 return -EIO;
213
214 *val = buf[1];
215 return 0;
216}
217
218static int sh532u_i2c_wr8(struct sh532u_info *info, u8 reg, u8 val)
219{
220 struct i2c_msg msg;
221 u8 buf[2];
222
223 buf[0] = reg;
224 buf[1] = val;
225 msg.addr = info->i2c_client->addr;
226 msg.flags = 0;
227 msg.len = 2;
228 msg.buf = &buf[0];
229 if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
230 return -EIO;
231
232 return 0;
233}
234
235static int sh532u_i2c_rd16(struct sh532u_info *info, u8 reg, u16 *val)
236{
237 struct i2c_msg msg[2];
238 u8 buf[3];
239
240 buf[0] = reg;
241 msg[0].addr = info->i2c_client->addr;
242 msg[0].flags = 0;
243 msg[0].len = 1;
244 msg[0].buf = &buf[0];
245 msg[1].addr = info->i2c_client->addr;
246 msg[1].flags = I2C_M_RD;
247 msg[1].len = 2;
248 msg[1].buf = &buf[1];
249 if (i2c_transfer(info->i2c_client->adapter, msg, 2) != 2)
250 return -EIO;
251
252 *val = (((u16)buf[1] << 8) | (u16)buf[2]);
253 return 0;
254}
255
256
257static int sh532u_i2c_wr16(struct sh532u_info *info, u8 reg, u16 val)
258{
259 struct i2c_msg msg;
260 u8 buf[3];
261
262 buf[0] = reg;
263 buf[1] = (u8)(val >> 8);
264 buf[2] = (u8)(val & 0xff);
265 msg.addr = info->i2c_client->addr;
266 msg.flags = 0;
267 msg.len = 3;
268 msg.buf = &buf[0];
269 if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
270 return -EIO;
271
272 return 0;
273}
274
275static int sh532u_i2c_rd32(struct sh532u_info *info, u8 addr, u8 reg, u32 *val)
276{
277 struct i2c_msg msg[2];
278 u8 buf[5];
279
280 buf[0] = reg;
281 if (addr) {
282 msg[0].addr = addr;
283 msg[1].addr = addr;
284 } else {
285 msg[0].addr = info->i2c_client->addr;
286 msg[1].addr = info->i2c_client->addr;
287 }
288 msg[0].flags = 0;
289 msg[0].len = 1;
290 msg[0].buf = &buf[0];
291 msg[1].flags = I2C_M_RD;
292 msg[1].len = 4;
293 msg[1].buf = &buf[1];
294 if (i2c_transfer(info->i2c_client->adapter, msg, 2) != 2)
295 return -EIO;
296
297 *val = (((u32)buf[4] << 24) | ((u32)buf[3] << 16) |
298 ((u32)buf[2] << 8) | ((u32)buf[1]));
299 return 0;
300}
301
302static void sh532u_gpio_en(struct sh532u_info *info, int val)
303{
304 if (info->pdata->gpio_en)
305 gpio_set_value_cansleep(info->pdata->gpio_en, val);
306}
307
308static void sh532u_gpio_reset(struct sh532u_info *info, int val)
309{
310 if (val) {
311 if (!info->gpio_flag_reset && info->pdata->gpio_reset) {
312 gpio_set_value_cansleep(info->pdata->gpio_reset, 0);
313 mdelay(1);
314 gpio_set_value_cansleep(info->pdata->gpio_reset, 1);
315 mdelay(10); /* delay for device startup */
316 info->gpio_flag_reset = 1;
317 }
318 } else {
319 info->gpio_flag_reset = 0;
320 }
321}
322
323static void sh532u_pm_regulator_put(struct nvc_regulator *sreg)
324{
325 regulator_put(sreg->vreg);
326 sreg->vreg = NULL;
327}
328
329static int sh532u_pm_regulator_get(struct sh532u_info *info,
330 struct nvc_regulator *sreg,
331 char vreg_name[])
332{
333 int err = 0;
334
335 sreg->vreg_flag = 0;
336 sreg->vreg = regulator_get(&info->i2c_client->dev, vreg_name);
337 if (IS_ERR_OR_NULL(sreg->vreg)) {
338 dev_err(&info->i2c_client->dev,
339 "%s err for regulator: %s err: %d\n",
340 __func__, vreg_name, (int)sreg->vreg);
341 err = PTR_ERR(sreg->vreg);
342 sreg->vreg = NULL;
343 } else {
344 sreg->vreg_name = vreg_name;
345 dev_dbg(&info->i2c_client->dev,
346 "%s vreg_name: %s\n",
347 __func__, sreg->vreg_name);
348 }
349 return err;
350}
351
352static int sh532u_pm_regulator_en(struct sh532u_info *info,
353 struct nvc_regulator *sreg)
354{
355 int err = 0;
356
357 if (!sreg->vreg_flag && (sreg->vreg != NULL)) {
358 err = regulator_enable(sreg->vreg);
359 if (!err) {
360 dev_dbg(&info->i2c_client->dev,
361 "%s vreg_name: %s\n",
362 __func__, sreg->vreg_name);
363 sreg->vreg_flag = 1;
364 err = 1; /* flag regulator state change */
365 } else {
366 dev_err(&info->i2c_client->dev,
367 "%s err, regulator: %s\n",
368 __func__, sreg->vreg_name);
369 }
370 }
371 return err;
372}
373
374static int sh532u_pm_regulator_dis(struct sh532u_info *info,
375 struct nvc_regulator *sreg)
376{
377 int err = 0;
378
379 if (sreg->vreg_flag && (sreg->vreg != NULL)) {
380 err = regulator_disable(sreg->vreg);
381 if (err)
382 dev_err(&info->i2c_client->dev,
383 "%s err, regulator: %s\n",
384 __func__, sreg->vreg_name);
385 }
386 sreg->vreg_flag = 0;
387 return err;
388}
389
390static int sh532u_pm_wr(struct sh532u_info *info, int pwr)
391{
392 int err = 0;
393
394 if ((info->pdata->cfg & (NVC_CFG_OFF2STDBY | NVC_CFG_BOOT_INIT)) &&
395 (pwr == NVC_PWR_OFF ||
396 pwr == NVC_PWR_STDBY_OFF))
397 pwr = NVC_PWR_STDBY;
398
399 if (pwr == info->pwr_dev)
400 return 0;
401
402 switch (pwr) {
403 case NVC_PWR_OFF_FORCE:
404 case NVC_PWR_OFF:
405 sh532u_gpio_en(info, 0);
406 err = sh532u_pm_regulator_dis(info, &info->vreg_vdd);
407 err |= sh532u_pm_regulator_dis(info, &info->vreg_i2c);
408 sh532u_gpio_reset(info, 0);
409 break;
410
411 case NVC_PWR_STDBY_OFF:
412 case NVC_PWR_STDBY:
413 err = sh532u_pm_regulator_en(info, &info->vreg_vdd);
414 err |= sh532u_pm_regulator_en(info, &info->vreg_i2c);
415 sh532u_gpio_en(info, 1);
416 sh532u_gpio_reset(info, 1);
417 err |= sh532u_i2c_wr8(info, STBY_211, 0x80);
418 err |= sh532u_i2c_wr8(info, CLKSEL_211, 0x38);
419 err |= sh532u_i2c_wr8(info, CLKSEL_211, 0x39);
420 break;
421
422 case NVC_PWR_COMM:
423 case NVC_PWR_ON:
424 err = sh532u_pm_regulator_en(info, &info->vreg_vdd);
425 err |= sh532u_pm_regulator_en(info, &info->vreg_i2c);
426 sh532u_gpio_en(info, 1);
427 sh532u_gpio_reset(info, 1);
428 err |= sh532u_i2c_wr8(info, CLKSEL_211, 0x38);
429 err |= sh532u_i2c_wr8(info, CLKSEL_211, 0x34);
430 err |= sh532u_i2c_wr8(info, STBY_211, 0xF0);
431 break;
432
433 default:
434 err = -EINVAL;
435 break;
436 }
437
438 if (err < 0) {
439 dev_err(&info->i2c_client->dev, "%s pwr err: %d\n",
440 __func__, pwr);
441 pwr = NVC_PWR_ERR;
442 }
443 info->pwr_dev = pwr;
444 if (err > 0)
445 return 0;
446
447 return err;
448}
449
450static int sh532u_pm_wr_s(struct sh532u_info *info, int pwr)
451{
452 int err1 = 0;
453 int err2 = 0;
454
455 if ((info->s_mode == NVC_SYNC_OFF) ||
456 (info->s_mode == NVC_SYNC_MASTER) ||
457 (info->s_mode == NVC_SYNC_STEREO))
458 err1 = sh532u_pm_wr(info, pwr);
459 if ((info->s_mode == NVC_SYNC_SLAVE) ||
460 (info->s_mode == NVC_SYNC_STEREO))
461 err2 = sh532u_pm_wr(info->s_info, pwr);
462 return err1 | err2;
463}
464
465static int sh532u_pm_api_wr(struct sh532u_info *info, int pwr)
466{
467 int err = 0;
468
469 if (!pwr || (pwr > NVC_PWR_ON))
470 return 0;
471
472 if (pwr > info->pwr_dev)
473 err = sh532u_pm_wr_s(info, pwr);
474 if (!err)
475 info->pwr_api = pwr;
476 else
477 info->pwr_api = NVC_PWR_ERR;
478 if (info->pdata->cfg & NVC_CFG_NOERR)
479 return 0;
480
481 return err;
482}
483
484static int sh532u_pm_dev_wr(struct sh532u_info *info, int pwr)
485{
486 if (pwr < info->pwr_api)
487 pwr = info->pwr_api;
488 if (info->sts == NVC_FOCUS_STS_WAIT_FOR_MOVE_END)
489 pwr = NVC_PWR_ON;
490 return sh532u_pm_wr(info, pwr);
491}
492
493static void sh532u_pm_exit(struct sh532u_info *info)
494{
495 sh532u_pm_wr(info, NVC_PWR_OFF_FORCE);
496 sh532u_pm_regulator_put(&info->vreg_vdd);
497 sh532u_pm_regulator_put(&info->vreg_i2c);
498 if (info->s_info != NULL) {
499 sh532u_pm_wr(info->s_info, NVC_PWR_OFF_FORCE);
500 sh532u_pm_regulator_put(&info->s_info->vreg_vdd);
501 sh532u_pm_regulator_put(&info->s_info->vreg_i2c);
502 }
503}
504
505static void sh532u_pm_init(struct sh532u_info *info)
506{
507 sh532u_pm_regulator_get(info, &info->vreg_vdd, "vdd");
508 sh532u_pm_regulator_get(info, &info->vreg_i2c, "vdd_i2c");
509}
510
511static int sh532u_dev_id(struct sh532u_info *info)
512{
513 u8 val;
514 int err;
515
516 err = sh532u_i2c_rd8(info, 0, HVCA_DEVICE_ID, &val);
517 if (!err && (val == SH532U_ID))
518 return 0;
519
520 return -ENODEV;
521}
522
523static void sh532u_sts_rd(struct sh532u_info *info)
524{
525 u8 us_tmp;
526 u16 us_smv_fin;
527 int err;
528
529 if (info->sts == NVC_FOCUS_STS_INITIALIZING)
530 return;
531
532 info->sts = NVC_FOCUS_STS_NO_DEVICE; /* assume I2C err */
533 err = sh532u_i2c_rd8(info, 0, STMVEN_211, &us_tmp);
534 err |= sh532u_i2c_rd16(info, RZ_211H, &us_smv_fin);
535 if (err)
536 return;
537
538 /* StepMove Error Handling, Unexpected Position */
539 if ((us_smv_fin == 0x7FFF) || (us_smv_fin == 0x8001))
540 /* Stop StepMove Operation */
541 sh532u_i2c_wr8(info, STMVEN_211, us_tmp & 0xFE);
542 if (us_tmp & STMVEN_ON) {
543 err = sh532u_i2c_rd8(info, 0, MSSET_211, &us_tmp);
544 if (!err) {
545 if (us_tmp & CHTGST_ON)
546 info->sts = NVC_FOCUS_STS_WAIT_FOR_SETTLE;
547 else
548 info->sts = NVC_FOCUS_STS_LENS_SETTLED;
549 }
550 } else {
551 info->sts = NVC_FOCUS_STS_WAIT_FOR_MOVE_END;
552 }
553}
554
555static s16 sh532u_rel2abs(struct sh532u_info *info, u32 rel_position)
556{
557 s16 abs_pos;
558
559 if (rel_position > info->cap.actuator_range)
560 rel_position = info->cap.actuator_range;
561 rel_position = info->cap.actuator_range - rel_position;
562 if (rel_position) {
563 rel_position *= info->abs_range;
564 rel_position /= info->cap.actuator_range;
565 }
566 abs_pos = (s16)(info->abs_base + rel_position);
567 if (abs_pos < info->cfg.limit_low)
568 abs_pos = info->cfg.limit_low;
569 if (abs_pos > info->cfg.limit_high)
570 abs_pos = info->cfg.limit_high;
571 return abs_pos;
572}
573
574static u32 sh532u_abs2rel(struct sh532u_info *info, s16 abs_position)
575{
576 u32 rel_pos;
577
578 if (abs_position > info->cfg.limit_high)
579 abs_position = info->cfg.limit_high;
580 if (abs_position < info->abs_base)
581 abs_position = info->abs_base;
582 rel_pos = (u32)(abs_position - info->abs_base);
583 rel_pos *= info->cap.actuator_range;
584 rel_pos /= info->abs_range;
585 if (rel_pos > info->cap.actuator_range)
586 rel_pos = info->cap.actuator_range;
587 rel_pos = info->cap.actuator_range - rel_pos;
588 return rel_pos;
589}
590
591static int sh532u_abs_pos_rd(struct sh532u_info *info, s16 *position)
592{
593 int err;
594 u16 abs_pos = 0;
595
596 err = sh532u_i2c_rd16(info, RZ_211H, &abs_pos);
597 *position = (s16)abs_pos;
598 return err;
599}
600
601static int sh532u_rel_pos_rd(struct sh532u_info *info, u32 *position)
602{
603 s16 abs_pos;
604 long msec;
605 int pos;
606 int err;
607
608 err = sh532u_abs_pos_rd(info, &abs_pos);
609 if (err)
610 return -EINVAL;
611
612 if ((abs_pos >= (info->pos_abs - STMV_SIZE)) &&
613 (abs_pos <= (info->pos_abs + STMV_SIZE))) {
614 pos = (int)info->pos_rel;
615 } else {
616 msec = jiffies;
617 msec -= info->pos_time_wr;
618 msec = msec * 1000 / HZ;
619 sh532u_sts_rd(info);
620 if ((info->sts == NVC_FOCUS_STS_LENS_SETTLED) ||
621 (msec > info->cfg.move_timeoutms)) {
622 pos = (int)info->pos_rel;
623 } else {
624 pos = (int)sh532u_abs2rel(info, abs_pos);
625 if ((pos == (info->pos_rel - 1)) ||
626 (pos == (info->pos_rel + 1)))
627 pos = (int)info->pos_rel;
628 }
629 }
630 if (pos < 0)
631 pos = 0;
632 *position = (u32)pos;
633 return 0;
634}
635
636static int sh532u_calibration(struct sh532u_info *info, bool use_defaults)
637{
638 u8 reg;
639 s16 abs_top;
640 u32 rel_range;
641 u32 rel_lo;
642 u32 rel_hi;
643 u32 step;
644 u32 loop_limit;
645 u32 i;
646 int err;
647 int ret = 0;
648
649 if (info->init_cal_flag)
650 return 0;
651
652 /* set defaults */
653 memcpy(&info->cfg, &sh532u_default_info, sizeof(info->cfg));
654 memcpy(&info->nvc, &sh532u_default_nvc, sizeof(info->nvc));
655 memcpy(&info->cap, &sh532u_default_cap, sizeof(info->cap));
656 if (info->pdata->i2c_addr_rom)
657 info->i2c_addr_rom = info->pdata->i2c_addr_rom;
658 else
659 info->i2c_addr_rom = sh532u_default_pdata.i2c_addr_rom;
660 /* set overrides if any */
661 if (info->pdata->nvc) {
662 if (info->pdata->nvc->fnumber)
663 info->nvc.fnumber = info->pdata->nvc->fnumber;
664 if (info->pdata->nvc->focal_length)
665 info->nvc.focal_length =
666 info->pdata->nvc->focal_length;
667 if (info->pdata->nvc->max_aperature)
668 info->nvc.max_aperature =
669 info->pdata->nvc->max_aperature;
670 }
671 if (info->pdata->cap) {
672 if (info->pdata->cap->actuator_range)
673 info->cap.actuator_range =
674 info->pdata->cap->actuator_range;
675 if (info->pdata->cap->settle_time)
676 info->cap.settle_time = info->pdata->cap->settle_time;
677 if (info->pdata->cap->focus_macro)
678 info->cap.focus_macro = info->pdata->cap->focus_macro;
679 if (info->pdata->cap->focus_hyper)
680 info->cap.focus_hyper = info->pdata->cap->focus_hyper;
681 if (info->pdata->cap->focus_infinity)
682 info->cap.focus_infinity =
683 info->pdata->cap->focus_infinity;
684 }
685 /*
686 * Get Inf1, Mac1
687 * Inf1 and Mac1 are the mechanical limit position.
688 * Inf1: top limit.
689 * Mac1: bottom limit.
690 */
691 err = sh532u_i2c_rd8(info, info->i2c_addr_rom, addrMac1, &reg);
692 if (!err && (reg != 0) && (reg != 0xFF))
693 info->cfg.limit_low = (reg<<8) & 0xff00;
694 ret = err;
695 err = sh532u_i2c_rd8(info, info->i2c_addr_rom, addrInf1, &reg);
696 if (!err && (reg != 0) && (reg != 0xFF))
697 info->cfg.limit_high = (reg<<8) & 0xff00;
698 ret |= err;
699 /*
700 * Get Inf2, Mac2
701 * Inf2 and Mac2 are the calibration data for SEMCO AF lens.
702 * Inf2: Best focus (lens position) when object distance is 1.2M.
703 * Mac2: Best focus (lens position) when object distance is 10cm.
704 */
705 err = sh532u_i2c_rd8(info, info->i2c_addr_rom, addrMac2, &reg);
706 if (!err && (reg != 0) && (reg != 0xFF))
707 info->cfg.pos_low = (reg << 8) & 0xff00;
708 ret |= err;
709 err = sh532u_i2c_rd8(info, info->i2c_addr_rom, addrInf2, &reg);
710 if (!err && (reg != 0) && (reg != 0xFF))
711 info->cfg.pos_high = (reg << 8) & 0xff00;
712 ret |= err;
713 /* set overrides */
714 if (info->pdata->info) {
715 if (info->pdata->info->pos_low)
716 info->cfg.pos_low = info->pdata->info->pos_low;
717 if (info->pdata->info->pos_high)
718 info->cfg.pos_high = info->pdata->info->pos_high;
719 if (info->pdata->info->limit_low)
720 info->cfg.limit_low = info->pdata->info->limit_low;
721 if (info->pdata->info->limit_high)
722 info->cfg.limit_high = info->pdata->info->limit_high;
723 if (info->pdata->info->move_timeoutms)
724 info->cfg.move_timeoutms =
725 info->pdata->info->move_timeoutms;
726 if (info->pdata->info->focus_hyper_ratio)
727 info->cfg.focus_hyper_ratio =
728 info->pdata->info->focus_hyper_ratio;
729 if (info->pdata->info->focus_hyper_div)
730 info->cfg.focus_hyper_div =
731 info->pdata->info->focus_hyper_div;
732 }
733 /*
734 * There is known to be many sh532u devices with no EPROM data.
735 * Using default data is known to reduce the sh532u performance since
736 * the defaults may no where be close to the correct values that
737 * should be used. However, we don't want to prevent the camera from
738 * starting due to the lack of the EPROM data.
739 * The following truth table shows the action to take at this point:
740 * DFLT = the use_defaults flag (used after multiple attempts)
741 * I2C = the I2C transactions to get the data.
742 * DATA = the needed data either from the EPROM or board file.
743 * DFLT I2C DATA Action
744 * --------------------------
745 * 0 FAIL FAIL Exit with -EIO
746 * 0 FAIL PASS Continue to calculations
747 * 0 PASS FAIL Use defaults
748 * 0 PASS PASS Continue to calculations
749 * 1 FAIL FAIL Use defaults
750 * 1 FAIL PASS Continue to calculations
751 * 1 PASS FAIL Use defaults
752 * 1 PASS PASS Continue to calculations
753 */
754 /* err = DATA where FAIL = 1 */
755 if (!info->cfg.pos_low || !info->cfg.pos_high ||
756 !info->cfg.limit_low || !info->cfg.limit_high)
757 err = 1;
758 else
759 err = 0;
760 /* Exit with -EIO */
761 if (!use_defaults && ret && err) {
762 dev_err(&info->i2c_client->dev, "%s ERR\n", __func__);
763 return -EIO;
764 }
765
766 /* Use defaults */
767 if (err) {
768 info->cfg.pos_low = SH532U_POS_LOW_DEFAULT;
769 info->cfg.pos_high = SH532U_POS_HIGH_DEFAULT;
770 info->cfg.limit_low = SH532U_POS_LOW_DEFAULT;
771 info->cfg.limit_high = SH532U_POS_HIGH_DEFAULT;
772 dev_err(&info->i2c_client->dev, "%s ERR: ERPOM data is void! "
773 "Focuser will use defaults that will cause "
774 "reduced functionality!\n", __func__);
775 }
776 if (info->cfg.pos_low < info->cfg.limit_low)
777 info->cfg.pos_low = info->cfg.limit_low;
778 if (info->cfg.pos_high > info->cfg.limit_high)
779 info->cfg.pos_high = info->cfg.limit_high;
780 dev_dbg(&info->i2c_client->dev, "%s pos_low=%d\n", __func__,
781 (int)info->cfg.pos_low);
782 dev_dbg(&info->i2c_client->dev, "%s pos_high=%d\n", __func__,
783 (int)info->cfg.pos_high);
784 dev_dbg(&info->i2c_client->dev, "%s limit_low=%d\n", __func__,
785 (int)info->cfg.limit_low);
786 dev_dbg(&info->i2c_client->dev, "%s limit_high=%d\n", __func__,
787 (int)info->cfg.limit_high);
788 /*
789 * calculate relative and absolute positions
790 * Note that relative values, what upper SW uses, are the
791 * abstraction of HW (absolute) values.
792 * |<--limit_low limit_high-->|
793 * | |<-------------------_ACTUATOR_RANGE------------------->| |
794 * -focus_inf -focus_mac
795 * |<---RI--->| |<---RM--->|
796 * -abs_base -pos_low -pos_high -abs_top
797 *
798 * The pos_low and pos_high are fixed absolute positions and correspond
799 * to the relative focus_infinity and focus_macro, respectively. We'd
800 * like to have "wiggle" room (RI and RM) around these relative
801 * positions so the loop below finds the best fit for RI and RM without
802 * passing the absolute limits.
803 * We want our _ACTUATOR_RANGE to be infinity on the 0 end and macro
804 * on the max end. However, the focuser HW is opposite this.
805 * Therefore we use the rel(ative)_lo/hi variables in the calculation
806 * loop and assign them the focus_infinity and focus_macro values.
807 */
808 rel_lo = (info->cap.actuator_range - info->cap.focus_macro);
809 rel_hi = info->cap.focus_infinity;
810 info->abs_range = (u32)(info->cfg.pos_high - info->cfg.pos_low);
811 loop_limit = (rel_lo > rel_hi) ? rel_lo : rel_hi;
812 for (i = 0; i <= loop_limit; i++) {
813 rel_range = info->cap.actuator_range - (rel_lo + rel_hi);
814 step = info->abs_range / rel_range;
815 info->abs_base = info->cfg.pos_low - (step * rel_lo);
816 abs_top = info->cfg.pos_high + (step * rel_hi);
817 if (info->abs_base < info->cfg.limit_low) {
818 if (rel_lo > 0)
819 rel_lo--;
820 }
821 if (abs_top > info->cfg.limit_high) {
822 if (rel_hi > 0)
823 rel_hi--;
824 }
825 if (info->abs_base >= info->cfg.limit_low &&
826 abs_top <= info->cfg.limit_high)
827 break;
828 }
829 info->cap.focus_hyper = info->abs_range;
830 info->abs_range = (u32)(abs_top - info->abs_base);
831 /* calculate absolute hyperfocus position */
832 info->cap.focus_hyper *= info->cfg.focus_hyper_ratio;
833 info->cap.focus_hyper /= info->cfg.focus_hyper_div;
834 abs_top = (s16)(info->cfg.pos_high - info->cap.focus_hyper);
835 /* update actual relative positions */
836 info->cap.focus_hyper = sh532u_abs2rel(info, abs_top);
837 info->cap.focus_infinity = sh532u_abs2rel(info, info->cfg.pos_high);
838 info->cap.focus_macro = sh532u_abs2rel(info, info->cfg.pos_low);
839 dev_dbg(&info->i2c_client->dev, "%s focus_macro=%u\n", __func__,
840 info->cap.focus_macro);
841 dev_dbg(&info->i2c_client->dev, "%s focus_infinity=%u\n", __func__,
842 info->cap.focus_infinity);
843 dev_dbg(&info->i2c_client->dev, "%s focus_hyper=%u\n", __func__,
844 info->cap.focus_hyper);
845 info->init_cal_flag = 1;
846 dev_dbg(&info->i2c_client->dev, "%s complete\n", __func__);
847 return 0;
848}
849
850 /* Write 1 byte data to the HVCA Drive IC by data type */
851static int sh532u_hvca_wr1(struct sh532u_info *info,
852 u8 ep_type, u8 ep_data1, u8 ep_addr)
853{
854 u8 us_data;
855 int err = 0;
856
857 switch (ep_type & 0xF0) {
858 case DIRECT_MODE:
859 us_data = ep_data1;
860 break;
861
862 case INDIRECT_EEPROM:
863 err = sh532u_i2c_rd8(info,
864 info->i2c_addr_rom,
865 ep_data1,
866 &us_data);
867 break;
868
869 case INDIRECT_HVCA:
870 err = sh532u_i2c_rd8(info, 0, ep_data1, &us_data);
871 break;
872
873 case MASK_AND:
874 err = sh532u_i2c_rd8(info, 0, ep_addr, &us_data);
875 us_data &= ep_data1;
876 break;
877
878 case MASK_OR:
879 err = sh532u_i2c_rd8(info, 0, ep_addr, &us_data);
880 us_data |= ep_data1;
881 break;
882
883 default:
884 err = -EINVAL;
885 }
886 if (!err)
887 err = sh532u_i2c_wr8(info, ep_addr, us_data);
888 return err;
889}
890
891 /* Write 2 byte data to the HVCA Drive IC by data type */
892static int sh532u_hvca_wr2(struct sh532u_info *info, u8 ep_type,
893 u8 ep_data1, u8 ep_data2, u8 ep_addr)
894{
895 u8 uc_data1;
896 u8 uc_data2;
897 u16 us_data;
898 int err = 0;
899
900 switch (ep_type & 0xF0) {
901 case DIRECT_MODE:
902 us_data = (((u16)ep_data1 << 8) & 0xFF00) |
903 ((u16)ep_data2 & 0x00FF);
904 break;
905
906 case INDIRECT_EEPROM:
907 err = sh532u_i2c_rd8(info,
908 info->i2c_addr_rom,
909 ep_data1,
910 &uc_data1);
911 err |= sh532u_i2c_rd8(info,
912 info->i2c_addr_rom,
913 ep_data2,
914 &uc_data2);
915 us_data = (((u16)uc_data1 << 8) & 0xFF00) |
916 ((u16)uc_data2 & 0x00FF);
917 break;
918
919 case INDIRECT_HVCA:
920 err = sh532u_i2c_rd8(info, 0, ep_data1, &uc_data1);
921 err |= sh532u_i2c_rd8(info, 0, ep_data2, &uc_data2);
922 us_data = (((u16)uc_data1 << 8) & 0xFF00) |
923 ((u16)uc_data2 & 0x00FF);
924 break;
925
926 case MASK_AND:
927 err = sh532u_i2c_rd16(info, ep_addr, &us_data);
928 us_data &= ((((u16)ep_data1 << 8) & 0xFF00) |
929 ((u16)ep_data2 & 0x00FF));
930 break;
931
932 case MASK_OR:
933 err = sh532u_i2c_rd16(info, ep_addr, &us_data);
934 us_data |= ((((u16)ep_data1 << 8) & 0xFF00) |
935 ((u16)ep_data2 & 0x00FF));
936 break;
937
938 default:
939 err = -EINVAL;
940 }
941 if (!err)
942 err = sh532u_i2c_wr16(info, ep_addr, us_data);
943 return err;
944}
945
946static int sh532u_dev_init(struct sh532u_info *info)
947{
948 int eeprom_reg;
949 unsigned eeprom_data = 0;
950 u8 ep_addr;
951 u8 ep_type;
952 u8 ep_data1;
953 u8 ep_data2;
954 int err;
955 int ret = 0;
956
957 err = sh532u_i2c_rd8(info, 0, SWTCH_211, &ep_data1);
958 ep_data2 = ep_data1;
959 err |= sh532u_i2c_rd8(info, 0, ANA1_211, &ep_data1);
960 ep_data2 |= ep_data1;
961 if (!err && ep_data2)
962 return 0; /* Already initialized */
963
964 info->sts = NVC_FOCUS_STS_INITIALIZING;
965 for (eeprom_reg = 0x30; eeprom_reg <= 0x013C; eeprom_reg += 4) {
966 if (eeprom_reg > 0xFF) {
967 /* use hardcoded data instead */
968 eeprom_data = sh532u_a2buf[(eeprom_reg & 0xFF) / 4];
969 } else {
970 err = (sh532u_i2c_rd32(info,
971 info->i2c_addr_rom,
972 eeprom_reg & 0xFF,
973 &eeprom_data));
974 if (err) {
975 ret |= err;
976 continue;
977 }
978 }
979
980 /* HVCA Address to write eeprom Data1,Data2 by the Data type */
981 ep_addr = (u8)(eeprom_data & 0x000000ff);
982 ep_type = (u8)((eeprom_data & 0x0000ff00) >> 8);
983 ep_data1 = (u8)((eeprom_data & 0x00ff0000) >> 16);
984 ep_data2 = (u8)((eeprom_data & 0xff000000) >> 24);
985 if (ep_addr == 0xFF)
986 break;
987
988 if (ep_addr == 0xDD) {
989 mdelay((unsigned int)((ep_data1 << 8) | ep_data2));
990 } else {
991 if ((ep_type & 0x0F) == DATA_1BYTE) {
992 err = sh532u_hvca_wr1(info,
993 ep_type,
994 ep_data1,
995 ep_addr);
996 } else {
997 err = sh532u_hvca_wr2(info,
998 ep_type,
999 ep_data1,
1000 ep_data2,
1001 ep_addr);
1002 }
1003 }
1004 ret |= err;
1005 }
1006
1007 err = ret;
1008 if (err)
1009 dev_err(&info->i2c_client->dev, "%s programming err=%d\n",
1010 __func__, err);
1011 err |= sh532u_calibration(info, false);
1012 info->sts = NVC_FOCUS_STS_LENS_SETTLED;
1013 return err;
1014}
1015
1016static int sh532u_pos_abs_wr(struct sh532u_info *info, s16 tar_pos)
1017{
1018 s16 cur_pos;
1019 s16 move_step;
1020 u16 move_distance;
1021 int err;
1022
1023 sh532u_pm_dev_wr(info, NVC_PWR_ON);
1024 err = sh532u_dev_init(info);
1025 if (err)
1026 return err;
1027
1028 /* Read Current Position */
1029 err = sh532u_abs_pos_rd(info, &cur_pos);
1030 if (err)
1031 return err;
1032
1033 dev_dbg(&info->i2c_client->dev, "%s cur_pos=%d tar_pos=%d\n",
1034 __func__, (int)cur_pos, (int)tar_pos);
1035 info->sts = NVC_FOCUS_STS_WAIT_FOR_MOVE_END;
1036 /* Check move distance to Target Position */
1037 move_distance = abs((int)cur_pos - (int)tar_pos);
1038 /* if move distance is shorter than MS1Z12(=Step width) */
1039 if (move_distance <= STMV_SIZE) {
1040 err = sh532u_i2c_wr8(info, MSSET_211,
1041 (INI_MSSET_211 | 0x01));
1042 err |= sh532u_i2c_wr16(info, MS1Z22_211H, tar_pos);
1043 } else {
1044 if (cur_pos < tar_pos)
1045 move_step = STMV_SIZE;
1046 else
1047 move_step = -STMV_SIZE;
1048 /* Set StepMove Target Positon */
1049 err = sh532u_i2c_wr16(info, MS1Z12_211H, move_step);
1050 err |= sh532u_i2c_wr16(info, STMVENDH_211, tar_pos);
1051 /* Start StepMove */
1052 err |= sh532u_i2c_wr8(info, STMVEN_211,
1053 (STMCHTG_ON |
1054 STMSV_ON |
1055 STMLFF_OFF |
1056 STMVEN_ON));
1057 }
1058 return err;
1059}
1060
1061static int sh532u_move_wait(struct sh532u_info *info)
1062{
1063 u16 us_smv_fin;
1064 u8 moveTime;
1065 u8 ucParMod;
1066 u8 tmp;
1067 int err;
1068
1069 moveTime = 0;
1070 do {
1071 mdelay(1);
1072 err = sh532u_i2c_rd8(info, 0, STMVEN_211, &ucParMod);
1073 err |= sh532u_i2c_rd16(info, RZ_211H, &us_smv_fin);
1074 if (err)
1075 return err;
1076
1077 /* StepMove Error Handling, Unexpected Position */
1078 if ((us_smv_fin == 0x7FFF) || (us_smv_fin == 0x8001)) {
1079 /* Stop StepMove Operation */
1080 err = sh532u_i2c_wr8(info, STMVEN_211,
1081 ucParMod & 0xFE);
1082 if (err)
1083 return err;
1084 }
1085
1086 moveTime++;
1087 /* Wait StepMove operation end */
1088 } while ((ucParMod & STMVEN_ON) && (moveTime < 50));
1089
1090 moveTime = 0;
1091 if ((ucParMod & 0x08) == STMCHTG_ON) {
1092 mdelay(5);
1093 do {
1094 mdelay(1);
1095 moveTime++;
1096 err = sh532u_i2c_rd8(info, 0, MSSET_211, &tmp);
1097 if (err)
1098 return err;
1099
1100 } while ((tmp & CHTGST_ON) && (moveTime < 15));
1101 }
1102 return err;
1103}
1104
1105static int sh532u_move_pulse(struct sh532u_info *info, s16 position)
1106{
1107 int err;
1108
1109 err = sh532u_pos_abs_wr(info, position);
1110 err |= sh532u_move_wait(info);
1111 return err;
1112}
1113
1114static int sh532u_hvca_pos_init(struct sh532u_info *info)
1115{
1116 s16 limit_bottom;
1117 s16 limit_top;
1118 int err;
1119
1120 limit_bottom = (((int)info->cfg.limit_low * 5) >> 3) & 0xFFC0;
1121 if (limit_bottom < info->cfg.limit_low)
1122 limit_bottom = info->cfg.limit_low;
1123 limit_top = (((int)info->cfg.limit_high * 5) >> 3) & 0xFFC0;
1124 if (limit_top > info->cfg.limit_high)
1125 limit_top = info->cfg.limit_high;
1126 err = sh532u_move_pulse(info, limit_bottom);
1127 err |= sh532u_move_pulse(info, limit_top);
1128 err |= sh532u_move_pulse(info, info->cfg.pos_high);
1129 return err;
1130}
1131
1132static int sh532u_pos_rel_wr(struct sh532u_info *info, u32 position)
1133{
1134 s16 abs_pos;
1135
1136 if (position > info->cap.actuator_range) {
1137 dev_err(&info->i2c_client->dev, "%s invalid position %u\n",
1138 __func__, position);
1139 return -EINVAL;
1140 }
1141
1142 abs_pos = sh532u_rel2abs(info, position);
1143 info->pos_rel = position;
1144 info->pos_abs = abs_pos;
1145 info->pos_time_wr = jiffies;
1146 return sh532u_pos_abs_wr(info, abs_pos);
1147}
1148
1149
1150static int sh532u_param_rd(struct sh532u_info *info, unsigned long arg)
1151{
1152 struct nvc_param params;
1153 const void *data_ptr;
1154 u32 data_size = 0;
1155 u32 position;
1156 int err;
1157
1158 if (copy_from_user(&params,
1159 (const void __user *)arg,
1160 sizeof(struct nvc_param))) {
1161 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
1162 __func__, __LINE__);
1163 return -EFAULT;
1164 }
1165
1166 if (info->s_mode == NVC_SYNC_SLAVE)
1167 info = info->s_info;
1168 switch (params.param) {
1169 case NVC_PARAM_LOCUS:
1170 sh532u_pm_dev_wr(info, NVC_PWR_COMM);
1171 err = sh532u_rel_pos_rd(info, &position);
1172 if (err && !(info->pdata->cfg & NVC_CFG_NOERR))
1173 return -EINVAL;
1174
1175 data_ptr = &position;
1176 data_size = sizeof(position);
1177 sh532u_pm_dev_wr(info, NVC_PWR_STDBY);
1178 dev_dbg(&info->i2c_client->dev, "%s LOCUS: %d\n",
1179 __func__, position);
1180 break;
1181
1182 case NVC_PARAM_FOCAL_LEN:
1183 data_ptr = &info->nvc.focal_length;
1184 data_size = sizeof(info->nvc.focal_length);
1185 dev_dbg(&info->i2c_client->dev, "%s FOCAL_LEN: %x\n",
1186 __func__, info->nvc.focal_length);
1187 break;
1188
1189 case NVC_PARAM_MAX_APERTURE:
1190 data_ptr = &info->nvc.max_aperature;
1191 data_size = sizeof(info->nvc.max_aperature);
1192 dev_dbg(&info->i2c_client->dev, "%s MAX_APERTURE: %x\n",
1193 __func__, info->nvc.max_aperature);
1194 break;
1195
1196 case NVC_PARAM_FNUMBER:
1197 data_ptr = &info->nvc.fnumber;
1198 data_size = sizeof(info->nvc.fnumber);
1199 dev_dbg(&info->i2c_client->dev, "%s FNUMBER: %x\n",
1200 __func__, info->nvc.fnumber);
1201 break;
1202
1203 case NVC_PARAM_CAPS:
1204 sh532u_pm_dev_wr(info, NVC_PWR_COMM);
1205 err = sh532u_calibration(info, true);
1206 sh532u_pm_dev_wr(info, NVC_PWR_STDBY);
1207 if (err)
1208 return -EIO;
1209
1210 data_ptr = &info->cap;
1211 /* there are different sizes depending on the version */
1212 /* send back just what's requested or our max size */
1213 if (params.sizeofvalue < sizeof(info->cap))
1214 data_size = params.sizeofvalue;
1215 else
1216 data_size = sizeof(info->cap);
1217 dev_dbg(&info->i2c_client->dev, "%s CAPS\n",
1218 __func__);
1219 break;
1220
1221 case NVC_PARAM_STS:
1222 data_ptr = &info->sts;
1223 data_size = sizeof(info->sts);
1224 dev_dbg(&info->i2c_client->dev, "%s STS: %d\n",
1225 __func__, info->sts);
1226 break;
1227
1228 case NVC_PARAM_STEREO:
1229 data_ptr = &info->s_mode;
1230 data_size = sizeof(info->s_mode);
1231 dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n",
1232 __func__, info->s_mode);
1233 break;
1234
1235 default:
1236 dev_err(&info->i2c_client->dev,
1237 "%s unsupported parameter: %d\n",
1238 __func__, params.param);
1239 return -EINVAL;
1240 }
1241
1242 if (params.sizeofvalue < data_size) {
1243 dev_err(&info->i2c_client->dev, "%s %d data size err\n",
1244 __func__, __LINE__);
1245 return -EINVAL;
1246 }
1247
1248 if (copy_to_user((void __user *)params.p_value,
1249 data_ptr,
1250 data_size)) {
1251 dev_err(&info->i2c_client->dev, "%s %d copy_to_user err\n",
1252 __func__, __LINE__);
1253 return -EFAULT;
1254 }
1255
1256 return 0;
1257}
1258
1259static int sh532u_param_wr_s(struct sh532u_info *info,
1260 struct nvc_param *params,
1261 u32 u32_val)
1262{
1263 int err;
1264
1265 switch (params->param) {
1266 case NVC_PARAM_LOCUS:
1267 dev_dbg(&info->i2c_client->dev, "%s LOCUS: %u\n",
1268 __func__, u32_val);
1269 err = sh532u_pos_rel_wr(info, u32_val);
1270 return err;
1271
1272 case NVC_PARAM_RESET:
1273 err = sh532u_pm_wr(info, NVC_PWR_OFF);
1274 err |= sh532u_pm_wr(info, NVC_PWR_ON);
1275 err |= sh532u_pm_wr(info, info->pwr_api);
1276 dev_dbg(&info->i2c_client->dev, "%s RESET: %d\n",
1277 __func__, err);
1278 return err;
1279
1280 case NVC_PARAM_SELF_TEST:
1281 err = sh532u_hvca_pos_init(info);
1282 dev_dbg(&info->i2c_client->dev, "%s SELF_TEST: %d\n",
1283 __func__, err);
1284 return err;
1285
1286 default:
1287 dev_err(&info->i2c_client->dev,
1288 "%s unsupported parameter: %d\n",
1289 __func__, params->param);
1290 return -EINVAL;
1291 }
1292}
1293
1294static int sh532u_param_wr(struct sh532u_info *info, unsigned long arg)
1295{
1296 struct nvc_param params;
1297 u8 val;
1298 u32 u32_val;
1299 int err = 0;
1300
1301 if (copy_from_user(&params,
1302 (const void __user *)arg,
1303 sizeof(struct nvc_param))) {
1304 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
1305 __func__, __LINE__);
1306 return -EFAULT;
1307 }
1308
1309 if (copy_from_user(&u32_val, (const void __user *)params.p_value,
1310 sizeof(u32_val))) {
1311 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
1312 __func__, __LINE__);
1313 return -EFAULT;
1314 }
1315
1316 /* parameters independent of sync mode */
1317 switch (params.param) {
1318 case NVC_PARAM_STEREO:
1319 dev_dbg(&info->i2c_client->dev, "%s STEREO: %u\n",
1320 __func__, u32_val);
1321 val = (u8)u32_val;
1322 if (val == info->s_mode)
1323 return 0;
1324
1325 switch (val) {
1326 case NVC_SYNC_OFF:
1327 info->s_mode = val;
1328 if (info->s_info != NULL) {
1329 info->s_info->s_mode = val;
1330 sh532u_pm_wr(info->s_info, NVC_PWR_OFF);
1331 }
1332 break;
1333
1334 case NVC_SYNC_MASTER:
1335 info->s_mode = val;
1336 if (info->s_info != NULL)
1337 info->s_info->s_mode = val;
1338 break;
1339
1340 case NVC_SYNC_SLAVE:
1341 if (info->s_info != NULL) {
1342 /* default slave lens position */
1343 err = sh532u_pos_rel_wr(info->s_info,
1344 info->s_info->cap.focus_infinity);
1345 if (!err) {
1346 info->s_mode = val;
1347 info->s_info->s_mode = val;
1348 } else {
1349 if (info->s_mode != NVC_SYNC_STEREO)
1350 sh532u_pm_wr(info->s_info,
1351 NVC_PWR_OFF);
1352 err = -EIO;
1353 }
1354 } else {
1355 err = -EINVAL;
1356 }
1357 break;
1358
1359 case NVC_SYNC_STEREO:
1360 if (info->s_info != NULL) {
1361 /* sync power */
1362 info->s_info->pwr_api = info->pwr_api;
1363 /* move slave lens to master position */
1364 err = sh532u_pos_rel_wr(info->s_info,
1365 info->pos_rel);
1366 if (!err) {
1367 info->s_mode = val;
1368 info->s_info->s_mode = val;
1369 } else {
1370 if (info->s_mode != NVC_SYNC_SLAVE)
1371 sh532u_pm_wr(info->s_info,
1372 NVC_PWR_OFF);
1373 err = -EIO;
1374 }
1375 } else {
1376 err = -EINVAL;
1377 }
1378 break;
1379
1380 default:
1381 err = -EINVAL;
1382 }
1383 if (info->pdata->cfg & NVC_CFG_NOERR)
1384 return 0;
1385
1386 return err;
1387
1388 default:
1389 /* parameters dependent on sync mode */
1390 switch (info->s_mode) {
1391 case NVC_SYNC_OFF:
1392 case NVC_SYNC_MASTER:
1393 return sh532u_param_wr_s(info, &params, u32_val);
1394
1395 case NVC_SYNC_SLAVE:
1396 return sh532u_param_wr_s(info->s_info,
1397 &params,
1398 u32_val);
1399
1400 case NVC_SYNC_STEREO:
1401 err = sh532u_param_wr_s(info, &params, u32_val);
1402 if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX))
1403 err |= sh532u_param_wr_s(info->s_info,
1404 &params,
1405 u32_val);
1406 return err;
1407
1408 default:
1409 dev_err(&info->i2c_client->dev, "%s %d internal err\n",
1410 __func__, __LINE__);
1411 return -EINVAL;
1412 }
1413 }
1414}
1415
1416static long sh532u_ioctl(struct file *file,
1417 unsigned int cmd,
1418 unsigned long arg)
1419{
1420 struct sh532u_info *info = file->private_data;
1421 int pwr;
1422
1423 switch (cmd) {
1424 case NVC_IOCTL_PARAM_WR:
1425 return sh532u_param_wr(info, arg);
1426
1427 case NVC_IOCTL_PARAM_RD:
1428 return sh532u_param_rd(info, arg);
1429
1430 case NVC_IOCTL_PWR_WR:
1431 /* This is a Guaranteed Level of Service (GLOS) call */
1432 pwr = (int)arg * 2;
1433 dev_dbg(&info->i2c_client->dev, "%s PWR: %d\n",
1434 __func__, pwr);
1435 return sh532u_pm_api_wr(info, pwr);
1436
1437 case NVC_IOCTL_PWR_RD:
1438 if (info->s_mode == NVC_SYNC_SLAVE)
1439 pwr = info->s_info->pwr_api / 2;
1440 else
1441 pwr = info->pwr_api / 2;
1442 dev_dbg(&info->i2c_client->dev, "%s PWR_RD: %d\n",
1443 __func__, pwr);
1444 if (copy_to_user((void __user *)arg, (const void *)&pwr,
1445 sizeof(pwr))) {
1446 dev_err(&info->i2c_client->dev,
1447 "%s copy_to_user err line %d\n",
1448 __func__, __LINE__);
1449 return -EFAULT;
1450 }
1451
1452 return 0;
1453
1454 default:
1455 dev_err(&info->i2c_client->dev, "%s unsupported ioctl: %x\n",
1456 __func__, cmd);
1457 return -EINVAL;
1458 }
1459}
1460
1461static int sh532u_sync_en(int dev1, int dev2)
1462{
1463 struct sh532u_info *sync1 = NULL;
1464 struct sh532u_info *sync2 = NULL;
1465 struct sh532u_info *pos = NULL;
1466
1467 rcu_read_lock();
1468 list_for_each_entry_rcu(pos, &sh532u_info_list, list) {
1469 if (pos->pdata->num == dev1) {
1470 sync1 = pos;
1471 break;
1472 }
1473 }
1474 pos = NULL;
1475 list_for_each_entry_rcu(pos, &sh532u_info_list, list) {
1476 if (pos->pdata->num == dev2) {
1477 sync2 = pos;
1478 break;
1479 }
1480 }
1481 rcu_read_unlock();
1482 if (sync1 != NULL)
1483 sync1->s_info = NULL;
1484 if (sync2 != NULL)
1485 sync2->s_info = NULL;
1486 if (!dev1 && !dev2)
1487 return 0; /* no err if default instance 0's used */
1488
1489 if (dev1 == dev2)
1490 return -EINVAL; /* err if sync instance is itself */
1491
1492 if ((sync1 != NULL) && (sync2 != NULL)) {
1493 sync1->s_info = sync2;
1494 sync2->s_info = sync1;
1495 }
1496 return 0;
1497}
1498
1499static int sh532u_sync_dis(struct sh532u_info *info)
1500{
1501 if (info->s_info != NULL) {
1502 info->s_info->s_mode = 0;
1503 info->s_info->s_info = NULL;
1504 info->s_mode = 0;
1505 info->s_info = NULL;
1506 return 0;
1507 }
1508
1509 return -EINVAL;
1510}
1511
1512static int sh532u_open(struct inode *inode, struct file *file)
1513{
1514 struct sh532u_info *info = NULL;
1515 struct sh532u_info *pos = NULL;
1516 int err;
1517
1518 rcu_read_lock();
1519 list_for_each_entry_rcu(pos, &sh532u_info_list, list) {
1520 if (pos->miscdev.minor == iminor(inode)) {
1521 info = pos;
1522 break;
1523 }
1524 }
1525 rcu_read_unlock();
1526 if (!info)
1527 return -ENODEV;
1528
1529 err = sh532u_sync_en(info->pdata->num, info->pdata->sync);
1530 if (err == -EINVAL)
1531 dev_err(&info->i2c_client->dev,
1532 "%s err: invalid num (%u) and sync (%u) instance\n",
1533 __func__, info->pdata->num, info->pdata->sync);
1534 if (atomic_xchg(&info->in_use, 1))
1535 return -EBUSY;
1536
1537 if (info->s_info != NULL) {
1538 if (atomic_xchg(&info->s_info->in_use, 1))
1539 return -EBUSY;
1540 }
1541
1542 file->private_data = info;
1543 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
1544 sh532u_pos_rel_wr(info, info->cap.focus_infinity);
1545 return 0;
1546}
1547
1548int sh532u_release(struct inode *inode, struct file *file)
1549{
1550 struct sh532u_info *info = file->private_data;
1551
1552 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
1553 sh532u_pm_wr_s(info, NVC_PWR_OFF);
1554 file->private_data = NULL;
1555 WARN_ON(!atomic_xchg(&info->in_use, 0));
1556 if (info->s_info != NULL)
1557 WARN_ON(!atomic_xchg(&info->s_info->in_use, 0));
1558 sh532u_sync_dis(info);
1559 return 0;
1560}
1561
1562static const struct file_operations sh532u_fileops = {
1563 .owner = THIS_MODULE,
1564 .open = sh532u_open,
1565 .unlocked_ioctl = sh532u_ioctl,
1566 .release = sh532u_release,
1567};
1568
1569static void sh532u_del(struct sh532u_info *info)
1570{
1571 sh532u_pm_exit(info);
1572 sh532u_sync_dis(info);
1573 spin_lock(&sh532u_spinlock);
1574 list_del_rcu(&info->list);
1575 spin_unlock(&sh532u_spinlock);
1576 synchronize_rcu();
1577}
1578
1579static int sh532u_remove(struct i2c_client *client)
1580{
1581 struct sh532u_info *info = i2c_get_clientdata(client);
1582
1583 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
1584 misc_deregister(&info->miscdev);
1585 sh532u_del(info);
1586 return 0;
1587}
1588
1589static int sh532u_probe(
1590 struct i2c_client *client,
1591 const struct i2c_device_id *id)
1592{
1593 struct sh532u_info *info = NULL;
1594 char dname[16];
1595 int err;
1596
1597 dev_dbg(&client->dev, "%s\n", __func__);
1598 info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
1599 if (info == NULL) {
1600 dev_err(&client->dev, "%s: kzalloc error\n", __func__);
1601 return -ENOMEM;
1602 }
1603
1604 info->i2c_client = client;
1605 if (client->dev.platform_data) {
1606 info->pdata = client->dev.platform_data;
1607 } else {
1608 info->pdata = &sh532u_default_pdata;
1609 dev_dbg(&client->dev,
1610 "%s No platform data. Using defaults.\n",
1611 __func__);
1612 }
1613 i2c_set_clientdata(client, info);
1614 INIT_LIST_HEAD(&info->list);
1615 spin_lock(&sh532u_spinlock);
1616 list_add_rcu(&info->list, &sh532u_info_list);
1617 spin_unlock(&sh532u_spinlock);
1618 sh532u_pm_init(info);
1619 sh532u_pm_dev_wr(info, NVC_PWR_COMM);
1620 err = sh532u_dev_id(info);
1621 if (err < 0) {
1622 dev_err(&client->dev, "%s device not found\n", __func__);
1623 sh532u_pm_wr(info, NVC_PWR_OFF);
1624 if (info->pdata->cfg & NVC_CFG_NODEV) {
1625 sh532u_del(info);
1626 return -ENODEV;
1627 }
1628 } else {
1629 dev_dbg(&client->dev, "%s device found\n", __func__);
1630 sh532u_calibration(info, false);
1631 if (info->pdata->cfg & NVC_CFG_BOOT_INIT) {
1632 /* initial move causes full initialization */
1633 sh532u_pos_rel_wr(info, info->cap.focus_infinity);
1634 } else {
1635 sh532u_pm_wr(info, NVC_PWR_OFF);
1636 }
1637 }
1638
1639 if (info->pdata->dev_name != 0)
1640 strcpy(dname, info->pdata->dev_name);
1641 else
1642 strcpy(dname, "sh532u");
1643 if (info->pdata->num)
1644 snprintf(dname, sizeof(dname), "%s.%u",
1645 dname, info->pdata->num);
1646 info->miscdev.name = dname;
1647 info->miscdev.fops = &sh532u_fileops;
1648 info->miscdev.minor = MISC_DYNAMIC_MINOR;
1649 if (misc_register(&info->miscdev)) {
1650 dev_err(&client->dev, "%s unable to register misc device %s\n",
1651 __func__, dname);
1652 sh532u_del(info);
1653 return -ENODEV;
1654 }
1655
1656 return 0;
1657}
1658
1659static const struct i2c_device_id sh532u_id[] = {
1660 { "sh532u", 0 },
1661 { },
1662};
1663
1664MODULE_DEVICE_TABLE(i2c, sh532u_id);
1665
1666static struct i2c_driver sh532u_i2c_driver = {
1667 .driver = {
1668 .name = "sh532u",
1669 .owner = THIS_MODULE,
1670 },
1671 .id_table = sh532u_id,
1672 .probe = sh532u_probe,
1673 .remove = sh532u_remove,
1674};
1675
1676static int __init sh532u_init(void)
1677{
1678 return i2c_add_driver(&sh532u_i2c_driver);
1679}
1680
1681static void __exit sh532u_exit(void)
1682{
1683 i2c_del_driver(&sh532u_i2c_driver);
1684}
1685
1686module_init(sh532u_init);
1687module_exit(sh532u_exit);
1688MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tegra/soc380.c b/drivers/media/video/tegra/soc380.c
new file mode 100644
index 00000000000..7f2c1361466
--- /dev/null
+++ b/drivers/media/video/tegra/soc380.c
@@ -0,0 +1,473 @@
1/*
2 * soc380.c - soc380 sensor driver
3 *
4 * Copyright (c) 2011, NVIDIA, All Rights Reserved.
5 *
6 * Contributors:
7 * Abhinav Sinha <absinha@nvidia.com>
8 *
9 * Leverage OV2710.c
10 *
11 * This file is licensed under the terms of the GNU General Public License
12 * version 2. This program is licensed "as is" without any warranty of any
13 * kind, whether express or implied.
14 */
15
16/**
17 * SetMode Sequence for 640x480. Phase 0. Sensor Dependent.
18 * This sequence should put sensor in streaming mode for 640x480
19 * This is usually given by the FAE or the sensor vendor.
20 */
21
22#include <linux/delay.h>
23#include <linux/fs.h>
24#include <linux/i2c.h>
25#include <linux/miscdevice.h>
26#include <linux/slab.h>
27#include <linux/uaccess.h>
28#include <media/soc380.h>
29
30struct soc380_reg {
31 u16 addr;
32 u16 val;
33};
34
35struct soc380_info {
36 int mode;
37 struct i2c_client *i2c_client;
38 struct soc380_platform_data *pdata;
39};
40
41#define SOC380_TABLE_WAIT_MS 0
42#define SOC380_TABLE_END 1
43#define SOC380_MAX_RETRIES 3
44
45static struct soc380_reg mode_640x480[] = {
46 {0x001A, 0x0011},
47
48 {SOC380_TABLE_WAIT_MS, 1},
49
50 {0x001A, 0x0010},
51
52 {SOC380_TABLE_WAIT_MS, 1},
53
54 {0x0018, 0x4028},
55 {0x001A, 0x0210},
56 {0x0010, 0x021c},
57 {0x0012, 0x0000},
58 {0x0014, 0x244B},
59
60 {SOC380_TABLE_WAIT_MS, 10},
61
62 {0x0014, 0x304B},
63
64 {SOC380_TABLE_WAIT_MS, 50},
65
66 {0x0014, 0xB04A},
67
68 {0x098C, 0x2703},
69 {0x0990, 0x0280},
70 {0x098C, 0x2705},
71 {0x0990, 0x01E0},
72 {0x098C, 0x2707},
73 {0x0990, 0x0280},
74 {0x098C, 0x2709},
75 {0x0990, 0x01E0},
76 {0x098C, 0x270D},
77 {0x0990, 0x0000},
78 {0x098C, 0x270F},
79 {0x0990, 0x0000},
80 {0x098C, 0x2711},
81 {0x0990, 0x01E7},
82 {0x098C, 0x2713},
83 {0x0990, 0x0287},
84 {0x098C, 0x2715},
85 {0x0990, 0x0001},
86 {0x098C, 0x2717},
87 {0x0990, 0x0026},
88 {0x098C, 0x2719},
89 {0x0990, 0x001A},
90 {0x098C, 0x271B},
91 {0x0990, 0x006B},
92 {0x098C, 0x271D},
93 {0x0990, 0x006B},
94 {0x098C, 0x271F},
95 {0x0990, 0x022A},
96 {0x098C, 0x2721},
97 {0x0990, 0x034A},
98 {0x098C, 0x2723},
99 {0x0990, 0x0000},
100 {0x098C, 0x2725},
101 {0x0990, 0x0000},
102 {0x098C, 0x2727},
103 {0x0990, 0x01E7},
104 {0x098C, 0x2729},
105 {0x0990, 0x0287},
106 {0x098C, 0x272B},
107 {0x0990, 0x0001},
108 {0x098C, 0x272D},
109 {0x0990, 0x0026},
110 {0x098C, 0x272F},
111 {0x0990, 0x001A},
112 {0x098C, 0x2731},
113 {0x0990, 0x006B},
114 {0x098C, 0x2733},
115 {0x0990, 0x006B},
116 {0x098C, 0x2735},
117 {0x0990, 0x022A},
118 {0x098C, 0x2737},
119 {0x0990, 0x034A},
120 {0x098C, 0x2739},
121 {0x0990, 0x0000},
122 {0x098C, 0x273B},
123 {0x0990, 0x027F},
124 {0x098C, 0x273D},
125 {0x0990, 0x0000},
126 {0x098C, 0x273F},
127 {0x0990, 0x01DF},
128 {0x098C, 0x2747},
129 {0x0990, 0x0000},
130 {0x098C, 0x2749},
131 {0x0990, 0x027F},
132 {0x098C, 0x274B},
133 {0x0990, 0x0000},
134 {0x098C, 0x274D},
135 {0x0990, 0x01DF},
136 {0x098C, 0x222D},
137 {0x0990, 0x008B},
138 {0x098C, 0xA408},
139 {0x0990, 0x0021},
140 {0x098C, 0xA409},
141 {0x0990, 0x0023},
142 {0x098C, 0xA40A},
143 {0x0990, 0x0028},
144 {0x098C, 0xA40B},
145 {0x0990, 0x002A},
146 {0x098C, 0x2411},
147 {0x0990, 0x008B},
148 {0x098C, 0x2413},
149 {0x0990, 0x00A6},
150 {0x098C, 0x2415},
151 {0x0990, 0x008B},
152 {0x098C, 0x2417},
153 {0x0990, 0x00A6},
154 {0x098C, 0xA404},
155 {0x0990, 0x0010},
156 {0x098C, 0xA40D},
157 {0x0990, 0x0002},
158 {0x098C, 0xA40E},
159 {0x0990, 0x0003},
160 {0x098C, 0xA410},
161 {0x0990, 0x000A},
162 {0x098C, 0xA215},
163 {0x0990, 0x0003},
164 {0x098C, 0xA20C},
165 {0x0990, 0x0003},
166
167 {0x098C, 0xA103},
168 {0x0990, 0x0006},
169 {SOC380_TABLE_WAIT_MS, 100},
170
171 {0x098C, 0xA103},
172 {0x0990, 0x0005},
173 {SOC380_TABLE_WAIT_MS, 50},
174
175 {SOC380_TABLE_END, 0x0000}
176};
177
178enum {
179 SOC380_MODE_680x480,
180};
181
182static struct soc380_reg *mode_table[] = {
183 [SOC380_MODE_680x480] = mode_640x480,
184};
185
186static int soc380_read_reg(struct i2c_client *client, u16 addr, u16 *val)
187{
188 int err;
189 struct i2c_msg msg[2];
190 unsigned char data[4];
191
192 if (!client->adapter)
193 return -ENODEV;
194
195 msg[0].addr = client->addr;
196 msg[0].flags = 0;
197 msg[0].len = 2;
198 msg[0].buf = data;
199
200 /* high byte goes out first */
201 data[0] = (u8) (addr >> 8);
202 data[1] = (u8) (addr & 0xff);
203
204 msg[1].addr = client->addr;
205 msg[1].flags = I2C_M_RD;
206 msg[1].len = 2;
207 msg[1].buf = data + 2;
208
209 err = i2c_transfer(client->adapter, msg, 2);
210
211 if (err != 2)
212 return -EINVAL;
213
214 *val = data[2] << 8 | data[3];
215
216 return 0;
217}
218
219static int soc380_write_reg(struct i2c_client *client, u16 addr, u16 val)
220{
221 int err;
222 struct i2c_msg msg;
223 unsigned char data[4];
224 int retry = 0;
225
226 if (!client->adapter)
227 return -ENODEV;
228
229 data[0] = (u8) (addr >> 8);
230 data[1] = (u8) (addr & 0xff);
231 data[2] = (u8) (val >> 8);
232 data[3] = (u8) (val & 0xff);
233
234 msg.addr = client->addr;
235 msg.flags = 0;
236 msg.len = 4;
237 msg.buf = data;
238
239 do {
240 err = i2c_transfer(client->adapter, &msg, 1);
241 if (err == 1)
242 return 0;
243 retry++;
244 pr_err("soc380: i2c transfer failed, retrying %x %x\n",
245 addr, val);
246 msleep(3);
247 } while (retry <= SOC380_MAX_RETRIES);
248
249 return err;
250}
251
252static int soc380_write_table(struct i2c_client *client,
253 const struct soc380_reg table[],
254 const struct soc380_reg override_list[],
255 int num_override_regs)
256{
257 int err;
258 const struct soc380_reg *next;
259 int i;
260 u16 val;
261
262 for (next = table; next->addr != SOC380_TABLE_END; next++) {
263 if (next->addr == SOC380_TABLE_WAIT_MS) {
264 msleep(next->val);
265 continue;
266 }
267
268 val = next->val;
269
270 /* When an override list is passed in, replace the reg */
271 /* value to write if the reg is in the list */
272 if (override_list) {
273 for (i = 0; i < num_override_regs; i++) {
274 if (next->addr == override_list[i].addr) {
275 val = override_list[i].val;
276 break;
277 }
278 }
279 }
280
281 err = soc380_write_reg(client, next->addr, val);
282 if (err)
283 return err;
284 }
285 return 0;
286}
287
288static int soc380_set_mode(struct soc380_info *info, struct soc380_mode *mode)
289{
290 int sensor_mode;
291 int err;
292
293 pr_info("%s: xres %u yres %u\n", __func__, mode->xres, mode->yres);
294 if (mode->xres == 640 && mode->yres == 480)
295 sensor_mode = SOC380_MODE_680x480;
296 else {
297 pr_err("%s: invalid resolution supplied to set mode %d %d\n",
298 __func__, mode->xres, mode->yres);
299 return -EINVAL;
300 }
301
302 err = soc380_write_table(info->i2c_client, mode_table[sensor_mode],
303 NULL, 0);
304 if (err)
305 return err;
306
307 info->mode = sensor_mode;
308 return 0;
309}
310
311static int soc380_get_status(struct soc380_info *info,
312 struct soc380_status *dev_status)
313{
314 int err;
315
316 err = soc380_write_reg(info->i2c_client, 0x98C, dev_status->data);
317 if (err)
318 return err;
319
320 err = soc380_read_reg(info->i2c_client, 0x0990,
321 (u16 *) &dev_status->status);
322 if (err)
323 return err;
324
325 return err;
326}
327
328static long soc380_ioctl(struct file *file,
329 unsigned int cmd, unsigned long arg)
330{
331 int err;
332 struct soc380_info *info = file->private_data;
333
334 switch (cmd) {
335 case SOC380_IOCTL_SET_MODE:
336 {
337 struct soc380_mode mode;
338 if (copy_from_user(&mode,
339 (const void __user *)arg,
340 sizeof(struct soc380_mode))) {
341 return -EFAULT;
342 }
343
344 return soc380_set_mode(info, &mode);
345 }
346 case SOC380_IOCTL_GET_STATUS:
347 {
348 struct soc380_status dev_status;
349 if (copy_from_user(&dev_status,
350 (const void __user *)arg,
351 sizeof(struct soc380_status))) {
352 return -EFAULT;
353 }
354
355 err = soc380_get_status(info, &dev_status);
356 if (err)
357 return err;
358 if (copy_to_user((void __user *)arg, &dev_status,
359 sizeof(struct soc380_status))) {
360 return -EFAULT;
361 }
362 return 0;
363 }
364 default:
365 return -EINVAL;
366 }
367 return 0;
368}
369
370static struct soc380_info *info;
371
372static int soc380_open(struct inode *inode, struct file *file)
373{
374 struct soc380_status dev_status;
375 int err;
376
377 file->private_data = info;
378 if (info->pdata && info->pdata->power_on)
379 info->pdata->power_on();
380
381 dev_status.data = 0;
382 dev_status.status = 0;
383 err = soc380_get_status(info, &dev_status);
384 return err;
385}
386
387int soc380_release(struct inode *inode, struct file *file)
388{
389 if (info->pdata && info->pdata->power_off)
390 info->pdata->power_off();
391 file->private_data = NULL;
392 return 0;
393}
394
395static const struct file_operations soc380_fileops = {
396 .owner = THIS_MODULE,
397 .open = soc380_open,
398 .unlocked_ioctl = soc380_ioctl,
399 .release = soc380_release,
400};
401
402static struct miscdevice soc380_device = {
403 .minor = MISC_DYNAMIC_MINOR,
404 .name = "soc380",
405 .fops = &soc380_fileops,
406};
407
408static int soc380_probe(struct i2c_client *client,
409 const struct i2c_device_id *id)
410{
411 int err;
412
413 pr_info("soc380: probing sensor.\n");
414
415 info = kzalloc(sizeof(struct soc380_info), GFP_KERNEL);
416 if (!info) {
417 pr_err("soc380: Unable to allocate memory!\n");
418 return -ENOMEM;
419 }
420
421 err = misc_register(&soc380_device);
422 if (err) {
423 pr_err("soc380: Unable to register misc device!\n");
424 kfree(info);
425 return err;
426 }
427
428 info->pdata = client->dev.platform_data;
429 info->i2c_client = client;
430
431 i2c_set_clientdata(client, info);
432 return 0;
433}
434
435static int soc380_remove(struct i2c_client *client)
436{
437 struct soc380_info *info;
438 info = i2c_get_clientdata(client);
439 misc_deregister(&soc380_device);
440 kfree(info);
441 return 0;
442}
443
444static const struct i2c_device_id soc380_id[] = {
445 { "soc380", 0 },
446 { },
447};
448
449MODULE_DEVICE_TABLE(i2c, soc380_id);
450
451static struct i2c_driver soc380_i2c_driver = {
452 .driver = {
453 .name = "soc380",
454 .owner = THIS_MODULE,
455 },
456 .probe = soc380_probe,
457 .remove = soc380_remove,
458 .id_table = soc380_id,
459};
460
461static int __init soc380_init(void)
462{
463 pr_info("soc380 sensor driver loading\n");
464 return i2c_add_driver(&soc380_i2c_driver);
465}
466
467static void __exit soc380_exit(void)
468{
469 i2c_del_driver(&soc380_i2c_driver);
470}
471
472module_init(soc380_init);
473module_exit(soc380_exit);
diff --git a/drivers/media/video/tegra/ssl3250a.c b/drivers/media/video/tegra/ssl3250a.c
new file mode 100644
index 00000000000..ef2c80a883c
--- /dev/null
+++ b/drivers/media/video/tegra/ssl3250a.c
@@ -0,0 +1,986 @@
1/*
2 * ssl3250a.c - ssl3250a flash/torch kernel driver
3 *
4 * Copyright (C) 2011 NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 * 02111-1307, USA
19 */
20
21/* Implementation
22 * --------------
23 * The board level details about the device need to be provided in the board
24 * file with the ssl3250a_platform_data structure.
25 * Standard among NVC kernel drivers in this structure is:
26 * .cfg = Use the NVC_CFG_ defines that are in nvc_torch.h.
27 * Descriptions of the configuration options are with the defines.
28 * This value is typically 0.
29 * .num = The number of the instance of the device. This should start at 1 and
30 * and increment for each device on the board. This number will be
31 * appended to the MISC driver name, Example: /dev/ssl3250a.1
32 * .sync = If there is a need to synchronize two devices, then this value is
33 * the number of the device instance this device is allowed to sync to.
34 * This is typically used for stereo applications.
35 * .dev_name = The MISC driver name the device registers as. If not used,
36 * then the part number of the device is used for the driver name.
37 * If using the NVC user driver then use the name found in this
38 * driver under _default_pdata.
39 *
40 * The following is specific to NVC kernel flash/torch drivers:
41 * .pinstate = a pointer to the nvc_torch_pin_state structure. This
42 * structure gives the details of which VI GPIO to use to trigger
43 * the flash. The mask tells which pin and the values is the
44 * level. For example, if VI GPIO pin 6 is used, then
45 * .mask = 0x0040
46 * .values = 0x0040
47 * If VI GPIO pin 0 is used, then
48 * .mask = 0x0001
49 * .values = 0x0001
50 * This is typically just one pin but there is some legacy
51 * here that insinuates more than one pin can be used.
52 * When the flash level is set, then the driver will return the
53 * value in values. When the flash level is off, the driver will
54 * return 0 for the values to deassert the signal.
55 * If a VI GPIO is not used, then the mask and values must be set
56 * to 0. The flash may then be triggered via I2C instead.
57 * However, a VI GPIO is strongly encouraged since it allows
58 * tighter timing with the picture taken as well as reduced power
59 * by asserting the trigger signal for only when needed.
60 * .max_amp_torch = Is the maximum torch value allowed. The value is 0 to
61 * _MAX_TORCH_LEVEL. This is to allow a limit to the amount
62 * of amps used. If left blank then _MAX_TORCH_LEVEL will be
63 * used.
64 * .max_amp_flash = Is the maximum flash value allowed. The value is 0 to
65 * _MAX_FLASH_LEVEL. This is to allow a limit to the amount
66 * of amps used. If left blank then _MAX_FLASH_LEVEL will be
67 * used.
68 *
69 * The following is specific to only this NVC kernel flash/torch driver:
70 * .gpio_act = Is the GPIO needed to control the ACT signal. If tied high,
71 * then this can be left blank.
72 *
73 * Power Requirements
74 * The board power file must contain the following labels for the power
75 * regulator(s) of this device:
76 * "vdd_i2c" = the power regulator for the I2C power.
77 * Note that this device is typically connected directly to the battery rail
78 * and does not need a source power regulator (vdd).
79 *
80 * The above values should be all that is needed to use the device with this
81 * driver. Modifications of this driver should not be needed.
82 */
83
84
85#include <linux/fs.h>
86#include <linux/i2c.h>
87#include <linux/miscdevice.h>
88#include <linux/slab.h>
89#include <linux/delay.h>
90#include <linux/uaccess.h>
91#include <linux/list.h>
92#include <linux/regulator/consumer.h>
93#include <linux/gpio.h>
94#include <media/nvc.h>
95#include <media/ssl3250a.h>
96
97#define SSL3250A_REG_AMP 0x00
98#define SSL3250A_REG_TMR 0x01
99#define SSL3250A_REG_STRB 0x02
100#define SSL3250A_REG_STS 0x03
101#define ssl3250a_flash_cap_size (sizeof(ssl3250a_flash_cap.numberoflevels) \
102 + (sizeof(ssl3250a_flash_cap.levels[0]) \
103 * (SSL3250A_MAX_FLASH_LEVEL + 1)))
104#define ssl3250a_torch_cap_size (sizeof(ssl3250a_torch_cap.numberoflevels) \
105 + (sizeof(ssl3250a_torch_cap.guidenum[0]) \
106 * (SSL3250A_MAX_TORCH_LEVEL + 1)))
107
108
109static struct nvc_torch_flash_capabilities ssl3250a_flash_cap = {
110 SSL3250A_MAX_FLASH_LEVEL + 1,
111 {
112 { 0, 0xFFFFFFFF, 0 },
113 { 215, 820, 20 },
114 { 230, 820, 20 },
115 { 245, 820, 20 },
116 { 260, 820, 20 },
117 { 275, 820, 20 },
118 { 290, 820, 20 },
119 { 305, 820, 20 },
120 { 320, 820, 20 },
121 { 335, 820, 20 },
122 { 350, 820, 20 },
123 { 365, 820, 20 },
124 { 380, 820, 20 },
125 { 395, 820, 20 },
126 { 410, 820, 20 },
127 { 425, 820, 20 },
128 { 440, 820, 20 },
129 { 455, 820, 20 },
130 { 470, 820, 20 },
131 { 485, 820, 20 },
132 { 500, 820, 20 }
133 }
134};
135
136static struct nvc_torch_torch_capabilities ssl3250a_torch_cap = {
137 SSL3250A_MAX_TORCH_LEVEL + 1,
138 {
139 0,
140 50,
141 65,
142 80,
143 95,
144 110,
145 125,
146 140,
147 155,
148 170,
149 185,
150 200
151 }
152};
153
154struct ssl3250a_info {
155 atomic_t in_use;
156 struct i2c_client *i2c_client;
157 struct ssl3250a_platform_data *pdata;
158 struct miscdevice miscdev;
159 struct list_head list;
160 int pwr_api;
161 int pwr_dev;
162 struct nvc_regulator vreg_i2c;
163 u8 s_mode;
164 struct ssl3250a_info *s_info;
165};
166
167static struct nvc_torch_pin_state ssl3250a_default_pinstate = {
168 .mask = 0x0000,
169 .values = 0x0000,
170};
171
172static struct ssl3250a_platform_data ssl3250a_default_pdata = {
173 .cfg = 0,
174 .num = 0,
175 .sync = 0,
176 .dev_name = "torch",
177 .pinstate = &ssl3250a_default_pinstate,
178 .max_amp_torch = SSL3250A_MAX_TORCH_LEVEL,
179 .max_amp_flash = SSL3250A_MAX_FLASH_LEVEL,
180};
181
182static LIST_HEAD(ssl3250a_info_list);
183static DEFINE_SPINLOCK(ssl3250a_spinlock);
184
185
186static int ssl3250a_i2c_rd(struct ssl3250a_info *info, u8 reg, u8 *val)
187{
188 struct i2c_msg msg[2];
189 u8 buf[2];
190
191 buf[0] = reg;
192 msg[0].addr = info->i2c_client->addr;
193 msg[0].flags = 0;
194 msg[0].len = 1;
195 msg[0].buf = &buf[0];
196 msg[1].addr = info->i2c_client->addr;
197 msg[1].flags = I2C_M_RD;
198 msg[1].len = 1;
199 msg[1].buf = &buf[1];
200 *val = 0;
201 if (i2c_transfer(info->i2c_client->adapter, msg, 2) != 2)
202 return -EIO;
203
204 *val = buf[1];
205 return 0;
206}
207
208static int ssl3250a_i2c_wr(struct ssl3250a_info *info, u8 reg, u8 val)
209{
210 struct i2c_msg msg;
211 u8 buf[2];
212
213 buf[0] = reg;
214 buf[1] = val;
215 msg.addr = info->i2c_client->addr;
216 msg.flags = 0;
217 msg.len = 2;
218 msg.buf = &buf[0];
219 if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
220 return -EIO;
221
222 return 0;
223}
224
225static void ssl3250a_gpio_act(struct ssl3250a_info *info, int val)
226{
227 int prev_val;
228
229 if (info->pdata->gpio_act) {
230 prev_val = gpio_get_value(info->pdata->gpio_act);
231 if (val != prev_val) {
232 gpio_set_value(info->pdata->gpio_act, val);
233 if (val)
234 mdelay(1); /* delay for device startup */
235 }
236 }
237}
238
239static void ssl3250a_pm_regulator_put(struct nvc_regulator *sreg)
240{
241 regulator_put(sreg->vreg);
242 sreg->vreg = NULL;
243}
244
245static int ssl3250a_pm_regulator_get(struct ssl3250a_info *info,
246 struct nvc_regulator *sreg,
247 char vreg_name[])
248{
249 int err = 0;
250
251 sreg->vreg_flag = 0;
252 sreg->vreg = regulator_get(&info->i2c_client->dev, vreg_name);
253 if (WARN_ON(IS_ERR(sreg->vreg))) {
254 dev_err(&info->i2c_client->dev,
255 "%s err for regulator: %s err: %d\n",
256 __func__, vreg_name, (int)sreg->vreg);
257 err = PTR_ERR(sreg->vreg);
258 sreg->vreg = NULL;
259 } else {
260 sreg->vreg_name = vreg_name;
261 dev_dbg(&info->i2c_client->dev,
262 "%s vreg_name: %s\n",
263 __func__, sreg->vreg_name);
264 }
265 return err;
266}
267
268static int ssl3250a_pm_regulator_en(struct ssl3250a_info *info,
269 struct nvc_regulator *sreg)
270{
271 int err = 0;
272
273 if (!sreg->vreg_flag && (sreg->vreg != NULL)) {
274 err = regulator_enable(sreg->vreg);
275 if (!err) {
276 dev_dbg(&info->i2c_client->dev,
277 "%s vreg_name: %s\n",
278 __func__, sreg->vreg_name);
279 sreg->vreg_flag = 1;
280 err = 1; /* flag regulator state change */
281 } else {
282 dev_err(&info->i2c_client->dev,
283 "%s err, regulator: %s\n",
284 __func__, sreg->vreg_name);
285 }
286 }
287 return err;
288}
289
290static int ssl3250a_pm_regulator_dis(struct ssl3250a_info *info,
291 struct nvc_regulator *sreg)
292{
293 int err = 0;
294
295 if (sreg->vreg_flag && (sreg->vreg != NULL)) {
296 err = regulator_disable(sreg->vreg);
297 if (!err)
298 dev_dbg(&info->i2c_client->dev,
299 "%s vreg_name: %s\n",
300 __func__, sreg->vreg_name);
301 else
302 dev_err(&info->i2c_client->dev,
303 "%s err, regulator: %s\n",
304 __func__, sreg->vreg_name);
305 }
306 sreg->vreg_flag = 0;
307 return err;
308}
309
310static int ssl3250a_pm_wr(struct ssl3250a_info *info, int pwr)
311{
312 int err = 0;
313
314 if (pwr == info->pwr_dev)
315 return 0;
316
317 switch (pwr) {
318 case NVC_PWR_OFF:
319 if ((info->pdata->cfg & NVC_CFG_OFF2STDBY) ||
320 (info->pdata->cfg & NVC_CFG_BOOT_INIT)) {
321 pwr = NVC_PWR_STDBY;
322 } else {
323 ssl3250a_gpio_act(info, 0);
324 err = ssl3250a_pm_regulator_dis(info, &info->vreg_i2c);
325 break;
326 }
327 case NVC_PWR_STDBY_OFF:
328 if ((info->pdata->cfg & NVC_CFG_OFF2STDBY) ||
329 (info->pdata->cfg & NVC_CFG_BOOT_INIT)) {
330 pwr = NVC_PWR_STDBY;
331 } else {
332 ssl3250a_gpio_act(info, 0);
333 err = ssl3250a_pm_regulator_en(info, &info->vreg_i2c);
334 break;
335 }
336 case NVC_PWR_STDBY:
337 err = ssl3250a_pm_regulator_en(info, &info->vreg_i2c);
338 ssl3250a_gpio_act(info, 1);
339 err |= ssl3250a_i2c_wr(info, SSL3250A_REG_AMP, 0x00);
340 break;
341
342 case NVC_PWR_COMM:
343 case NVC_PWR_ON:
344 err = ssl3250a_pm_regulator_en(info, &info->vreg_i2c);
345 ssl3250a_gpio_act(info, 1);
346 break;
347
348 default:
349 err = -EINVAL;
350 break;
351 }
352
353 if (err < 0) {
354 dev_err(&info->i2c_client->dev, "%s error\n", __func__);
355 pwr = NVC_PWR_ERR;
356 }
357 info->pwr_dev = pwr;
358 if (err > 0)
359 return 0;
360
361 return err;
362}
363
364static int ssl3250a_pm_wr_s(struct ssl3250a_info *info, int pwr)
365{
366 int err1 = 0;
367 int err2 = 0;
368
369 if ((info->s_mode == NVC_SYNC_OFF) ||
370 (info->s_mode == NVC_SYNC_MASTER) ||
371 (info->s_mode == NVC_SYNC_STEREO))
372 err1 = ssl3250a_pm_wr(info, pwr);
373 if ((info->s_mode == NVC_SYNC_SLAVE) ||
374 (info->s_mode == NVC_SYNC_STEREO))
375 err2 = ssl3250a_pm_wr(info->s_info, pwr);
376 return err1 | err2;
377}
378
379static int ssl3250a_pm_api_wr(struct ssl3250a_info *info, int pwr)
380{
381 int err = 0;
382
383 if (!pwr || (pwr > NVC_PWR_ON))
384 return 0;
385
386 if (pwr > info->pwr_dev)
387 err = ssl3250a_pm_wr_s(info, pwr);
388 if (!err)
389 info->pwr_api = pwr;
390 else
391 info->pwr_api = NVC_PWR_ERR;
392 if (info->pdata->cfg & NVC_CFG_NOERR)
393 return 0;
394
395 return err;
396}
397
398static int ssl3250a_pm_dev_wr(struct ssl3250a_info *info, int pwr)
399{
400 if (pwr < info->pwr_api)
401 pwr = info->pwr_api;
402 return ssl3250a_pm_wr(info, pwr);
403}
404
405static void ssl3250a_pm_exit(struct ssl3250a_info *info)
406{
407 ssl3250a_pm_wr_s(info, NVC_PWR_OFF);
408 ssl3250a_pm_regulator_put(&info->vreg_i2c);
409}
410
411static void ssl3250a_pm_init(struct ssl3250a_info *info)
412{
413 ssl3250a_pm_regulator_get(info, &info->vreg_i2c, "vdd_i2c");
414}
415
416static int ssl3250a_dev_id(struct ssl3250a_info *info)
417{
418 u8 addr;
419 u8 reg;
420 int err;
421
422 ssl3250a_pm_dev_wr(info, NVC_PWR_COMM);
423 /* There isn't a device ID so we just check that all the registers
424 * equal their startup defaults, which in this case, is 0.
425 */
426 for (addr = 0; addr < SSL3250A_REG_STS; addr++) {
427 err = ssl3250a_i2c_rd(info, addr, &reg);
428 if (err) {
429 break;
430 } else {
431 if (reg) {
432 err = -ENODEV;
433 break;
434 }
435 }
436 }
437 ssl3250a_pm_dev_wr(info, NVC_PWR_OFF);
438 return err;
439}
440
441static int ssl3250a_param_rd(struct ssl3250a_info *info, long arg)
442{
443 struct nvc_param params;
444 struct nvc_torch_pin_state pinstate;
445 const void *data_ptr;
446 u32 data_size = 0;
447 int err;
448 u8 reg;
449
450 if (copy_from_user(&params,
451 (const void __user *)arg,
452 sizeof(struct nvc_param))) {
453 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
454 __func__, __LINE__);
455 return -EINVAL;
456 }
457
458 if (info->s_mode == NVC_SYNC_SLAVE)
459 info = info->s_info;
460 switch (params.param) {
461 case NVC_PARAM_FLASH_CAPS:
462 dev_dbg(&info->i2c_client->dev, "%s FLASH_CAPS\n", __func__);
463 data_ptr = &ssl3250a_flash_cap;
464 data_size = ssl3250a_flash_cap_size;
465 break;
466
467 case NVC_PARAM_FLASH_LEVEL:
468 ssl3250a_pm_dev_wr(info, NVC_PWR_COMM);
469 err = ssl3250a_i2c_rd(info, SSL3250A_REG_AMP, &reg);
470 ssl3250a_pm_dev_wr(info, NVC_PWR_OFF);
471 if (err < 0)
472 return err;
473
474 reg >>= 3; /*7:3=flash amps*/
475 reg &= 0x1F; /*4:0=flash amps*/
476 if (reg < 12) /*flash starts at 12*/
477 reg = 0; /*<12=torch or off*/
478 else
479 reg -= 11; /*create flash index*/
480 dev_dbg(&info->i2c_client->dev, "%s FLASH_LEVEL: %u\n",
481 __func__,
482 (unsigned)ssl3250a_flash_cap.levels[reg].guidenum);
483 data_ptr = &ssl3250a_flash_cap.levels[reg].guidenum;
484 data_size = sizeof(ssl3250a_flash_cap.levels[reg].guidenum);
485 break;
486
487 case NVC_PARAM_TORCH_CAPS:
488 dev_dbg(&info->i2c_client->dev, "%s TORCH_CAPS\n", __func__);
489 data_ptr = &ssl3250a_torch_cap;
490 data_size = ssl3250a_torch_cap_size;
491 break;
492
493 case NVC_PARAM_TORCH_LEVEL:
494 ssl3250a_pm_dev_wr(info, NVC_PWR_COMM);
495 err = ssl3250a_i2c_rd(info, SSL3250A_REG_AMP, &reg);
496 ssl3250a_pm_dev_wr(info, NVC_PWR_OFF);
497 if (err < 0)
498 return err;
499
500 reg >>= 3; /*7:3=torch amps*/
501 reg &= 0x1F; /*4:0=torch amps*/
502 if (reg > 11) /*flash starts at 12*/
503 reg = 0; /*>11=flash mode (torch off)*/
504 dev_dbg(&info->i2c_client->dev, "%s TORCH_LEVEL: %u\n",
505 __func__,
506 (unsigned)ssl3250a_torch_cap.guidenum[reg]);
507 data_ptr = &ssl3250a_torch_cap.guidenum[reg];
508 data_size = sizeof(ssl3250a_torch_cap.guidenum[reg]);
509 break;
510
511 case NVC_PARAM_FLASH_PIN_STATE:
512 pinstate.mask = info->pdata->pinstate->mask;
513 ssl3250a_pm_dev_wr(info, NVC_PWR_COMM);
514 err = ssl3250a_i2c_rd(info, SSL3250A_REG_AMP, &reg);
515 ssl3250a_pm_dev_wr(info, NVC_PWR_OFF);
516 if (err < 0)
517 return err;
518
519 reg >>= 3; /*7:3=flash amps*/
520 reg &= 0x1F; /*4:0=flash amps*/
521 if (reg < 12) /*flash starts at 12*/
522 pinstate.values = 0; /*deassert strobe*/
523 else
524 /*assert strobe*/
525 pinstate.values = info->pdata->pinstate->values;
526 dev_dbg(&info->i2c_client->dev, "%s FLASH_PIN_STATE: %x&%x\n",
527 __func__, pinstate.mask, pinstate.values);
528 data_ptr = &pinstate;
529 data_size = sizeof(struct nvc_torch_pin_state);
530 break;
531
532 case NVC_PARAM_STEREO:
533 dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n",
534 __func__, info->s_mode);
535 data_ptr = &info->s_mode;
536 data_size = sizeof(info->s_mode);
537 break;
538
539 default:
540 dev_err(&info->i2c_client->dev,
541 "%s unsupported parameter: %d\n",
542 __func__, params.param);
543 return -EINVAL;
544 }
545
546 if (params.sizeofvalue < data_size) {
547 dev_err(&info->i2c_client->dev,
548 "%s data size mismatch %d != %d\n",
549 __func__, params.sizeofvalue, data_size);
550 return -EINVAL;
551 }
552
553 if (copy_to_user((void __user *)params.p_value,
554 data_ptr,
555 data_size)) {
556 dev_err(&info->i2c_client->dev,
557 "%s copy_to_user err line %d\n",
558 __func__, __LINE__);
559 return -EFAULT;
560 }
561
562 return 0;
563}
564
565static int ssl3250a_param_wr_s(struct ssl3250a_info *info,
566 struct nvc_param *params,
567 u8 val)
568{
569 int err;
570
571 switch (params->param) {
572 case NVC_PARAM_FLASH_LEVEL:
573 dev_dbg(&info->i2c_client->dev, "%s FLASH_LEVEL: %d\n",
574 __func__, val);
575 ssl3250a_pm_dev_wr(info, NVC_PWR_ON);
576 if (val > ssl3250a_default_pdata.max_amp_flash)
577 val = ssl3250a_default_pdata.max_amp_flash;
578 /*Amp limit values are in the board-sensors file.*/
579 if (info->pdata->max_amp_flash &&
580 (val > info->pdata->max_amp_flash))
581 val = info->pdata->max_amp_flash;
582 if (val) {
583 val += 11; /*flash starts at 12*/
584 val <<= 3; /*7:3=flash/torch amps*/
585 }
586 err = ssl3250a_i2c_wr(info, SSL3250A_REG_AMP, val);
587 if (!val) /*turn pwr off if no flash && no pwr_api*/
588 ssl3250a_pm_dev_wr(info, NVC_PWR_OFF);
589 return err;
590
591 case NVC_PARAM_TORCH_LEVEL:
592 dev_dbg(&info->i2c_client->dev, "%s TORCH_LEVEL: %d\n",
593 __func__, val);
594 ssl3250a_pm_dev_wr(info, NVC_PWR_ON);
595 if (val > ssl3250a_default_pdata.max_amp_torch)
596 val = ssl3250a_default_pdata.max_amp_torch;
597 /*Amp limit values are in the board-sensors file.*/
598 if (info->pdata->max_amp_torch &&
599 (val > info->pdata->max_amp_torch))
600 val = info->pdata->max_amp_torch;
601 if (val)
602 val <<= 3; /*7:3=flash/torch amps*/
603 err = ssl3250a_i2c_wr(info, SSL3250A_REG_AMP, val);
604 if (!val) /*turn pwr off if no torch && no pwr_api*/
605 ssl3250a_pm_dev_wr(info, NVC_PWR_OFF);
606 return err;
607
608 case NVC_PARAM_FLASH_PIN_STATE:
609 dev_dbg(&info->i2c_client->dev, "%s FLASH_PIN_STATE: %d\n",
610 __func__, val);
611 if (val)
612 val = 0x01; /*0:0=soft trigger*/
613 return ssl3250a_i2c_wr(info, SSL3250A_REG_STRB, val);
614
615 default:
616 dev_err(&info->i2c_client->dev,
617 "%s unsupported parameter: %d\n",
618 __func__, params->param);
619 return -EINVAL;
620 }
621}
622
623static int ssl3250a_param_wr(struct ssl3250a_info *info, long arg)
624{
625 struct nvc_param params;
626 u8 val;
627 int err = 0;
628
629 if (copy_from_user(&params,
630 (const void __user *)arg,
631 sizeof(struct nvc_param))) {
632 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
633 __func__, __LINE__);
634 return -EINVAL;
635 }
636
637 if (copy_from_user(&val, (const void __user *)params.p_value,
638 sizeof(val))) {
639 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
640 __func__, __LINE__);
641 return -EINVAL;
642 }
643
644 /* parameters independent of sync mode */
645 switch (params.param) {
646 case NVC_PARAM_STEREO:
647 dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n",
648 __func__, (int)val);
649 if (val == info->s_mode)
650 return 0;
651
652 switch (val) {
653 case NVC_SYNC_OFF:
654 info->s_mode = val;
655 if (info->s_info != NULL) {
656 info->s_info->s_mode = val;
657 ssl3250a_pm_wr(info->s_info, NVC_PWR_OFF);
658 }
659 break;
660
661 case NVC_SYNC_MASTER:
662 info->s_mode = val;
663 if (info->s_info != NULL)
664 info->s_info->s_mode = val;
665 break;
666
667 case NVC_SYNC_SLAVE:
668 case NVC_SYNC_STEREO:
669 if (info->s_info != NULL) {
670 /* sync power */
671 info->s_info->pwr_api = info->pwr_api;
672 err = ssl3250a_pm_wr(info->s_info,
673 info->pwr_dev);
674 if (!err) {
675 info->s_mode = val;
676 info->s_info->s_mode = val;
677 } else {
678 ssl3250a_pm_wr(info->s_info,
679 NVC_PWR_OFF);
680 err = -EIO;
681 }
682 } else {
683 err = -EINVAL;
684 }
685 break;
686
687 default:
688 err = -EINVAL;
689 }
690 if (info->pdata->cfg & NVC_CFG_NOERR)
691 return 0;
692
693 return err;
694
695 default:
696 /* parameters dependent on sync mode */
697 switch (info->s_mode) {
698 case NVC_SYNC_OFF:
699 case NVC_SYNC_MASTER:
700 return ssl3250a_param_wr_s(info, &params, val);
701
702 case NVC_SYNC_SLAVE:
703 return ssl3250a_param_wr_s(info->s_info,
704 &params,
705 val);
706
707 case NVC_SYNC_STEREO:
708 err = ssl3250a_param_wr_s(info, &params, val);
709 if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX))
710 err |= ssl3250a_param_wr_s(info->s_info,
711 &params,
712 val);
713 return err;
714
715 default:
716 dev_err(&info->i2c_client->dev, "%s %d internal err\n",
717 __func__, __LINE__);
718 return -EINVAL;
719 }
720 }
721}
722
723static long ssl3250a_ioctl(struct file *file,
724 unsigned int cmd,
725 unsigned long arg)
726{
727 struct ssl3250a_info *info = file->private_data;
728 int pwr;
729
730 switch (cmd) {
731 case NVC_IOCTL_PARAM_WR:
732 return ssl3250a_param_wr(info, arg);
733
734 case NVC_IOCTL_PARAM_RD:
735 return ssl3250a_param_rd(info, arg);
736
737 case NVC_IOCTL_PWR_WR:
738 /* This is a Guaranteed Level of Service (GLOS) call */
739 pwr = (int)arg * 2;
740 dev_dbg(&info->i2c_client->dev, "%s PWR_WR: %d\n",
741 __func__, pwr);
742 return ssl3250a_pm_api_wr(info, pwr);
743
744 case NVC_IOCTL_PWR_RD:
745 if (info->s_mode == NVC_SYNC_SLAVE)
746 pwr = info->s_info->pwr_api / 2;
747 else
748 pwr = info->pwr_api / 2;
749 dev_dbg(&info->i2c_client->dev, "%s PWR_RD: %d\n",
750 __func__, pwr);
751 if (copy_to_user((void __user *)arg, (const void *)&pwr,
752 sizeof(pwr))) {
753 dev_err(&info->i2c_client->dev,
754 "%s copy_to_user err line %d\n",
755 __func__, __LINE__);
756 return -EFAULT;
757 }
758
759 return 0;
760
761 default:
762 dev_err(&info->i2c_client->dev, "%s unsupported ioctl: %x\n",
763 __func__, cmd);
764 return -EINVAL;
765 }
766}
767
768static int ssl3250a_sync_en(int dev1, int dev2)
769{
770 struct ssl3250a_info *sync1 = NULL;
771 struct ssl3250a_info *sync2 = NULL;
772 struct ssl3250a_info *pos = NULL;
773
774 rcu_read_lock();
775 list_for_each_entry_rcu(pos, &ssl3250a_info_list, list) {
776 if (pos->pdata->num == dev1) {
777 sync1 = pos;
778 break;
779 }
780 }
781 pos = NULL;
782 list_for_each_entry_rcu(pos, &ssl3250a_info_list, list) {
783 if (pos->pdata->num == dev2) {
784 sync2 = pos;
785 break;
786 }
787 }
788 rcu_read_unlock();
789 if (sync1 != NULL)
790 sync1->s_info = NULL;
791 if (sync2 != NULL)
792 sync2->s_info = NULL;
793 if (!dev1 && !dev2)
794 return 0; /* no err if default instance 0's used */
795
796 if (dev1 == dev2)
797 return -EINVAL; /* err if sync instance is itself */
798
799 if ((sync1 != NULL) && (sync2 != NULL)) {
800 sync1->s_info = sync2;
801 sync2->s_info = sync1;
802 }
803
804 return 0;
805}
806
807static int ssl3250a_sync_dis(struct ssl3250a_info *info)
808{
809 if (info->s_info != NULL) {
810 info->s_info->s_mode = 0;
811 info->s_info->s_info = NULL;
812 info->s_mode = 0;
813 info->s_info = NULL;
814 return 0;
815 }
816
817 return -EINVAL;
818}
819
820static int ssl3250a_open(struct inode *inode, struct file *file)
821{
822 struct ssl3250a_info *info = NULL;
823 struct ssl3250a_info *pos = NULL;
824 int err;
825
826 rcu_read_lock();
827 list_for_each_entry_rcu(pos, &ssl3250a_info_list, list) {
828 if (pos->miscdev.minor == iminor(inode)) {
829 info = pos;
830 break;
831 }
832 }
833 rcu_read_unlock();
834 if (!info)
835 return -ENODEV;
836
837 err = ssl3250a_sync_en(info->pdata->num, info->pdata->sync);
838 if (err == -EINVAL)
839 dev_err(&info->i2c_client->dev,
840 "%s err: invalid num (%u) and sync (%u) instance\n",
841 __func__, info->pdata->num, info->pdata->sync);
842 if (atomic_xchg(&info->in_use, 1))
843 return -EBUSY;
844
845 if (info->s_info != NULL) {
846 if (atomic_xchg(&info->s_info->in_use, 1))
847 return -EBUSY;
848 }
849
850 file->private_data = info;
851 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
852 return 0;
853}
854
855static int ssl3250a_release(struct inode *inode, struct file *file)
856{
857 struct ssl3250a_info *info = file->private_data;
858
859 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
860 ssl3250a_pm_wr_s(info, NVC_PWR_OFF);
861 file->private_data = NULL;
862 WARN_ON(!atomic_xchg(&info->in_use, 0));
863 if (info->s_info != NULL)
864 WARN_ON(!atomic_xchg(&info->s_info->in_use, 0));
865 ssl3250a_sync_dis(info);
866 return 0;
867}
868
869static const struct file_operations ssl3250a_fileops = {
870 .owner = THIS_MODULE,
871 .open = ssl3250a_open,
872 .unlocked_ioctl = ssl3250a_ioctl,
873 .release = ssl3250a_release,
874};
875
876static void ssl3250a_del(struct ssl3250a_info *info)
877{
878 ssl3250a_pm_exit(info);
879 ssl3250a_sync_dis(info);
880 spin_lock(&ssl3250a_spinlock);
881 list_del_rcu(&info->list);
882 spin_unlock(&ssl3250a_spinlock);
883 synchronize_rcu();
884}
885
886static int ssl3250a_remove(struct i2c_client *client)
887{
888 struct ssl3250a_info *info = i2c_get_clientdata(client);
889
890 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
891 misc_deregister(&info->miscdev);
892 ssl3250a_del(info);
893 return 0;
894}
895
896static int ssl3250a_probe(
897 struct i2c_client *client,
898 const struct i2c_device_id *id)
899{
900 struct ssl3250a_info *info;
901 char dname[16];
902 int err;
903
904 dev_dbg(&client->dev, "%s\n", __func__);
905 info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
906 if (info == NULL) {
907 dev_err(&client->dev, "%s: kzalloc error\n", __func__);
908 return -ENOMEM;
909 }
910
911 info->i2c_client = client;
912 if (client->dev.platform_data) {
913 info->pdata = client->dev.platform_data;
914 } else {
915 info->pdata = &ssl3250a_default_pdata;
916 dev_dbg(&client->dev,
917 "%s No platform data. Using defaults.\n",
918 __func__);
919 }
920 i2c_set_clientdata(client, info);
921 INIT_LIST_HEAD(&info->list);
922 spin_lock(&ssl3250a_spinlock);
923 list_add_rcu(&info->list, &ssl3250a_info_list);
924 spin_unlock(&ssl3250a_spinlock);
925 ssl3250a_pm_init(info);
926 err = ssl3250a_dev_id(info);
927 if (err < 0) {
928 dev_err(&client->dev, "%s device not found\n", __func__);
929 if (info->pdata->cfg & NVC_CFG_NODEV) {
930 ssl3250a_del(info);
931 return -ENODEV;
932 }
933 } else {
934 dev_dbg(&client->dev, "%s device found\n", __func__);
935 }
936
937 if (info->pdata->dev_name != 0)
938 strcpy(dname, info->pdata->dev_name);
939 else
940 strcpy(dname, "ssl3250a");
941 if (info->pdata->num)
942 snprintf(dname, sizeof(dname), "%s.%u",
943 dname, info->pdata->num);
944 info->miscdev.name = dname;
945 info->miscdev.fops = &ssl3250a_fileops;
946 info->miscdev.minor = MISC_DYNAMIC_MINOR;
947 if (misc_register(&info->miscdev)) {
948 dev_err(&client->dev, "%s unable to register misc device %s\n",
949 __func__, dname);
950 ssl3250a_del(info);
951 return -ENODEV;
952 }
953
954 return 0;
955}
956
957static const struct i2c_device_id ssl3250a_id[] = {
958 { "ssl3250a", 0 },
959 { },
960};
961
962MODULE_DEVICE_TABLE(i2c, ssl3250a_id);
963
964static struct i2c_driver ssl3250a_i2c_driver = {
965 .driver = {
966 .name = "ssl3250a",
967 .owner = THIS_MODULE,
968 },
969 .id_table = ssl3250a_id,
970 .probe = ssl3250a_probe,
971 .remove = ssl3250a_remove,
972};
973
974static int __init ssl3250a_init(void)
975{
976 return i2c_add_driver(&ssl3250a_i2c_driver);
977}
978
979static void __exit ssl3250a_exit(void)
980{
981 i2c_del_driver(&ssl3250a_i2c_driver);
982}
983
984module_init(ssl3250a_init);
985module_exit(ssl3250a_exit);
986MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tegra/tegra_camera.c b/drivers/media/video/tegra/tegra_camera.c
new file mode 100644
index 00000000000..e90b130bcd6
--- /dev/null
+++ b/drivers/media/video/tegra/tegra_camera.c
@@ -0,0 +1,612 @@
1/*
2 * drivers/media/video/tegra/tegra_camera.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Copyright (C) 2012 Nvidia Corp
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/miscdevice.h>
19#include <linux/platform_device.h>
20#include <linux/ioctl.h>
21#include <linux/fs.h>
22#include <linux/device.h>
23#include <linux/regulator/consumer.h>
24#include <linux/clk.h>
25#include <linux/io.h>
26#include <linux/uaccess.h>
27#include <linux/delay.h>
28#include <mach/iomap.h>
29#include <mach/clk.h>
30#include <mach/powergate.h>
31
32#include <media/tegra_camera.h>
33
34/* Eventually this should handle all clock and reset calls for the isp, vi,
35 * vi_sensor, and csi modules, replacing nvrm and nvos completely for camera
36 */
37#define TEGRA_CAMERA_NAME "tegra_camera"
38
39struct tegra_camera_dev {
40 struct device *dev;
41 struct miscdevice misc_dev;
42 struct clk *isp_clk;
43 struct clk *vi_clk;
44 struct clk *vi_sensor_clk;
45 struct clk *csus_clk;
46 struct clk *csi_clk;
47 struct clk *emc_clk;
48 struct regulator *reg;
49 struct tegra_camera_clk_info info;
50 struct mutex tegra_camera_lock;
51 int power_refcnt;
52};
53
54struct tegra_camera_block {
55 int (*enable) (struct tegra_camera_dev *dev);
56 int (*disable) (struct tegra_camera_dev *dev);
57 bool is_enabled;
58};
59
60static int tegra_camera_enable_isp(struct tegra_camera_dev *dev)
61{
62 return clk_enable(dev->isp_clk);
63}
64
65static int tegra_camera_disable_isp(struct tegra_camera_dev *dev)
66{
67 clk_disable(dev->isp_clk);
68 return 0;
69}
70
71static int tegra_camera_enable_vi(struct tegra_camera_dev *dev)
72{
73 int ret = 0;
74
75 ret |= clk_enable(dev->vi_clk);
76 ret |= clk_enable(dev->vi_sensor_clk);
77 ret |= clk_enable(dev->csus_clk);
78 return ret;
79}
80
81static int tegra_camera_disable_vi(struct tegra_camera_dev *dev)
82{
83 clk_disable(dev->vi_clk);
84 clk_disable(dev->vi_sensor_clk);
85 clk_disable(dev->csus_clk);
86 return 0;
87}
88
89static int tegra_camera_enable_csi(struct tegra_camera_dev *dev)
90{
91 return clk_enable(dev->csi_clk);
92}
93
94static int tegra_camera_disable_csi(struct tegra_camera_dev *dev)
95{
96 clk_disable(dev->csi_clk);
97 return 0;
98}
99
100static int tegra_camera_enable_emc(struct tegra_camera_dev *dev)
101{
102 /* tegra_camera wasn't added as a user of emc_clk until 3x.
103 set to 150 MHz, will likely need to be increased as we support
104 sensors with higher framerates and resolutions. */
105 clk_enable(dev->emc_clk);
106#ifdef CONFIG_ARCH_TEGRA_2x_SOC
107 clk_set_rate(dev->emc_clk, 300000000);
108#else
109 clk_set_rate(dev->emc_clk, 150000000);
110#endif
111 return 0;
112}
113
114static int tegra_camera_disable_emc(struct tegra_camera_dev *dev)
115{
116 clk_disable(dev->emc_clk);
117 return 0;
118}
119
120struct tegra_camera_block tegra_camera_block[] = {
121 [TEGRA_CAMERA_MODULE_ISP] = {tegra_camera_enable_isp,
122 tegra_camera_disable_isp, false},
123 [TEGRA_CAMERA_MODULE_VI] = {tegra_camera_enable_vi,
124 tegra_camera_disable_vi, false},
125 [TEGRA_CAMERA_MODULE_CSI] = {tegra_camera_enable_csi,
126 tegra_camera_disable_csi, false},
127};
128
129#define TEGRA_CAMERA_VI_CLK_SEL_INTERNAL 0
130#define TEGRA_CAMERA_VI_CLK_SEL_EXTERNAL (1<<24)
131#define TEGRA_CAMERA_PD2VI_CLK_SEL_VI_SENSOR_CLK (1<<25)
132#define TEGRA_CAMERA_PD2VI_CLK_SEL_PD2VI_CLK 0
133
134static bool tegra_camera_enabled(struct tegra_camera_dev *dev)
135{
136 bool ret = false;
137
138 mutex_lock(&dev->tegra_camera_lock);
139 ret = tegra_camera_block[TEGRA_CAMERA_MODULE_ISP].is_enabled == true ||
140 tegra_camera_block[TEGRA_CAMERA_MODULE_VI].is_enabled == true ||
141 tegra_camera_block[TEGRA_CAMERA_MODULE_CSI].is_enabled == true;
142 mutex_unlock(&dev->tegra_camera_lock);
143 return ret;
144}
145
146static int tegra_camera_clk_set_rate(struct tegra_camera_dev *dev)
147{
148 struct clk *clk, *clk_parent;
149 struct tegra_camera_clk_info *info = &dev->info;
150 unsigned long parent_rate, parent_div_rate, parent_div_rate_pre;
151
152 if (!info) {
153 dev_err(dev->dev,
154 "%s: no clock info %d\n",
155 __func__, info->id);
156 return -EINVAL;
157 }
158
159 if (info->id != TEGRA_CAMERA_MODULE_VI) {
160 dev_err(dev->dev,
161 "%s: set rate only aplies to vi module %d\n",
162 __func__, info->id);
163 return -EINVAL;
164 }
165
166 switch (info->clk_id) {
167 case TEGRA_CAMERA_VI_CLK:
168 clk = dev->vi_clk;
169 break;
170 case TEGRA_CAMERA_VI_SENSOR_CLK:
171 clk = dev->vi_sensor_clk;
172 break;
173 default:
174 dev_err(dev->dev,
175 "%s: invalid clk id for set rate %d\n",
176 __func__, info->clk_id);
177 return -EINVAL;
178 }
179
180 clk_parent = clk_get_parent(clk);
181 parent_rate = clk_get_rate(clk_parent);
182 dev_dbg(dev->dev, "%s: clk_id=%d, parent_rate=%lu, clk_rate=%lu\n",
183 __func__, info->clk_id, parent_rate, info->rate);
184 parent_div_rate = parent_rate;
185 parent_div_rate_pre = parent_rate;
186
187 /*
188 * The requested clock rate from user space should be respected.
189 * This loop is to search the clock rate that is higher than requested
190 * clock.
191 */
192 while (parent_div_rate >= info->rate) {
193 parent_div_rate_pre = parent_div_rate;
194 parent_div_rate = clk_round_rate(clk, parent_div_rate-1);
195 }
196
197 dev_dbg(dev->dev, "%s: set_rate=%lu",
198 __func__, parent_div_rate_pre);
199
200 clk_set_rate(clk, parent_div_rate_pre);
201
202 if (info->clk_id == TEGRA_CAMERA_VI_CLK) {
203 /*
204 * bit 25: 0 = pd2vi_Clk, 1 = vi_sensor_clk
205 * bit 24: 0 = internal clock, 1 = external clock(pd2vi_clk)
206 */
207 if (info->flag == TEGRA_CAMERA_ENABLE_PD2VI_CLK)
208 tegra_clk_cfg_ex(clk, TEGRA_CLK_VI_INP_SEL, 2);
209
210#ifdef CONFIG_ARCH_TEGRA_2x_SOC
211 u32 val;
212 void __iomem *apb_misc = IO_ADDRESS(TEGRA_APB_MISC_BASE);
213 val = readl(apb_misc + 0x42c);
214 writel(val | 0x1, apb_misc + 0x42c);
215#endif
216 }
217
218 info->rate = clk_get_rate(clk);
219 dev_dbg(dev->dev, "%s: get_rate=%lu",
220 __func__, info->rate);
221 return 0;
222
223}
224static int tegra_camera_reset(struct tegra_camera_dev *dev, uint id)
225{
226 struct clk *clk;
227
228 switch (id) {
229 case TEGRA_CAMERA_MODULE_VI:
230 clk = dev->vi_clk;
231 break;
232 case TEGRA_CAMERA_MODULE_ISP:
233 clk = dev->isp_clk;
234 break;
235 case TEGRA_CAMERA_MODULE_CSI:
236 clk = dev->csi_clk;
237 break;
238 default:
239 return -EINVAL;
240 }
241 tegra_periph_reset_assert(clk);
242 udelay(10);
243 tegra_periph_reset_deassert(clk);
244
245 return 0;
246}
247
248static int tegra_camera_power_on(struct tegra_camera_dev *dev)
249{
250 int ret = 0;
251
252 if (dev->power_refcnt++ == 0) {
253 /* Enable external power */
254 if (dev->reg) {
255 ret = regulator_enable(dev->reg);
256 if (ret) {
257 dev_err(dev->dev,
258 "%s: enable csi regulator failed.\n",
259 __func__);
260 return ret;
261 }
262 }
263#ifndef CONFIG_ARCH_TEGRA_2x_SOC
264 /* Unpowergate VE */
265 ret = tegra_unpowergate_partition(TEGRA_POWERGATE_VENC);
266 if (ret)
267 dev_err(dev->dev,
268 "%s: unpowergate failed.\n",
269 __func__);
270#endif
271 }
272
273 return ret;
274}
275
276static int tegra_camera_power_off(struct tegra_camera_dev *dev)
277{
278 int ret = 0;
279
280 if (--dev->power_refcnt == 0) {
281#ifndef CONFIG_ARCH_TEGRA_2x_SOC
282 /* Powergate VE */
283 ret = tegra_powergate_partition(TEGRA_POWERGATE_VENC);
284 if (ret)
285 dev_err(dev->dev,
286 "%s: powergate failed.\n",
287 __func__);
288#endif
289 /* Disable external power */
290 if (dev->reg) {
291 ret = regulator_disable(dev->reg);
292 if (ret) {
293 dev_err(dev->dev,
294 "%s: disable csi regulator failed.\n",
295 __func__);
296 return ret;
297 }
298 }
299 }
300 return ret;
301}
302
303static long tegra_camera_ioctl(struct file *file,
304 unsigned int cmd, unsigned long arg)
305{
306 uint id;
307 struct tegra_camera_dev *dev = file->private_data;
308
309 /* first element of arg must be u32 with id of module to talk to */
310 if (copy_from_user(&id, (const void __user *)arg, sizeof(uint))) {
311 dev_err(dev->dev,
312 "%s: Failed to copy arg from user", __func__);
313 return -EFAULT;
314 }
315
316 if (id >= ARRAY_SIZE(tegra_camera_block)) {
317 dev_err(dev->dev,
318 "%s: Invalid id to tegra isp ioctl%d\n",
319 __func__, id);
320 return -EINVAL;
321 }
322
323 switch (cmd) {
324 case TEGRA_CAMERA_IOCTL_ENABLE:
325 {
326 int ret = 0;
327
328 mutex_lock(&dev->tegra_camera_lock);
329 /* Unpowergate camera blocks (vi, csi and isp)
330 before enabling clocks */
331 ret = tegra_camera_power_on(dev);
332 if (ret) {
333 dev->power_refcnt = 0;
334 mutex_unlock(&dev->tegra_camera_lock);
335 return ret;
336 }
337
338 if (!tegra_camera_block[id].is_enabled) {
339 ret = tegra_camera_block[id].enable(dev);
340 tegra_camera_block[id].is_enabled = true;
341 }
342 mutex_unlock(&dev->tegra_camera_lock);
343 return ret;
344 }
345 case TEGRA_CAMERA_IOCTL_DISABLE:
346 {
347 int ret = 0;
348
349 mutex_lock(&dev->tegra_camera_lock);
350 if (tegra_camera_block[id].is_enabled) {
351 ret = tegra_camera_block[id].disable(dev);
352 tegra_camera_block[id].is_enabled = false;
353 }
354 /* Powergate camera blocks (vi, csi and isp)
355 after disabling all the clocks */
356 if (!ret) {
357 ret = tegra_camera_power_off(dev);
358 }
359 mutex_unlock(&dev->tegra_camera_lock);
360 return ret;
361 }
362 case TEGRA_CAMERA_IOCTL_CLK_SET_RATE:
363 {
364 int ret;
365
366 if (copy_from_user(&dev->info, (const void __user *)arg,
367 sizeof(struct tegra_camera_clk_info))) {
368 dev_err(dev->dev,
369 "%s: Failed to copy arg from user\n", __func__);
370 return -EFAULT;
371 }
372 ret = tegra_camera_clk_set_rate(dev);
373 if (ret)
374 return ret;
375 if (copy_to_user((void __user *)arg, &dev->info,
376 sizeof(struct tegra_camera_clk_info))) {
377 dev_err(dev->dev,
378 "%s: Failed to copy arg to user\n", __func__);
379 return -EFAULT;
380 }
381 return 0;
382 }
383 case TEGRA_CAMERA_IOCTL_RESET:
384 return tegra_camera_reset(dev, id);
385 default:
386 dev_err(dev->dev,
387 "%s: Unknown tegra_camera ioctl.\n", __func__);
388 return -EINVAL;
389 }
390 return 0;
391}
392
393static int tegra_camera_open(struct inode *inode, struct file *file)
394{
395 struct miscdevice *miscdev = file->private_data;
396 struct tegra_camera_dev *dev = container_of(miscdev,
397 struct tegra_camera_dev,
398 misc_dev);
399 dev_info(dev->dev, "%s\n", __func__);
400 file->private_data = dev;
401
402 tegra_camera_enable_emc(dev);
403
404 return 0;
405}
406
407static int tegra_camera_release(struct inode *inode, struct file *file)
408{
409 int i, err;
410 struct tegra_camera_dev *dev = file->private_data;
411
412 dev_info(dev->dev, "%s\n", __func__);
413 for (i = 0; i < ARRAY_SIZE(tegra_camera_block); i++)
414 if (tegra_camera_block[i].is_enabled) {
415 tegra_camera_block[i].disable(dev);
416 tegra_camera_block[i].is_enabled = false;
417 }
418
419 /* If camera blocks are not powergated yet, do it now */
420 if (dev->power_refcnt > 0) {
421 mutex_lock(&dev->tegra_camera_lock);
422#ifndef CONFIG_ARCH_TEGRA_2x_SOC
423 err = tegra_powergate_partition(TEGRA_POWERGATE_VENC);
424 if (err)
425 dev_err(dev->dev, "%s: powergate failed.\n", __func__);
426#endif
427 dev->power_refcnt = 0;
428 mutex_unlock(&dev->tegra_camera_lock);
429 }
430
431 tegra_camera_disable_emc(dev);
432
433 return 0;
434}
435
436static const struct file_operations tegra_camera_fops = {
437 .owner = THIS_MODULE,
438 .open = tegra_camera_open,
439 .unlocked_ioctl = tegra_camera_ioctl,
440 .release = tegra_camera_release,
441};
442
443static int tegra_camera_clk_get(struct platform_device *pdev, const char *name,
444 struct clk **clk)
445{
446 *clk = clk_get(&pdev->dev, name);
447 if (IS_ERR_OR_NULL(*clk)) {
448 dev_err(&pdev->dev, "%s: unable to get clock for %s\n",
449 __func__, name);
450 *clk = NULL;
451 return PTR_ERR(*clk);
452 }
453 return 0;
454}
455
456static int tegra_camera_probe(struct platform_device *pdev)
457{
458 int err;
459 struct tegra_camera_dev *dev;
460
461 dev_info(&pdev->dev, "%s\n", __func__);
462 dev = devm_kzalloc(&pdev->dev, sizeof(struct tegra_camera_dev),
463 GFP_KERNEL);
464 if (!dev) {
465 err = -ENOMEM;
466 dev_err(&pdev->dev, "%s: unable to allocate memory\n",
467 __func__);
468 goto alloc_err;
469 }
470
471 mutex_init(&dev->tegra_camera_lock);
472
473 /* Powergate VE when boot */
474 mutex_lock(&dev->tegra_camera_lock);
475 dev->power_refcnt = 0;
476#ifndef CONFIG_ARCH_TEGRA_2x_SOC
477 err = tegra_powergate_partition(TEGRA_POWERGATE_VENC);
478 if (err)
479 dev_err(&pdev->dev, "%s: powergate failed.\n", __func__);
480#endif
481 mutex_unlock(&dev->tegra_camera_lock);
482
483 dev->dev = &pdev->dev;
484
485 /* Get regulator pointer */
486#ifdef CONFIG_ARCH_TEGRA_2x_SOC
487 dev->reg = regulator_get(&pdev->dev, "vcsi");
488#else
489 dev->reg = regulator_get(&pdev->dev, "avdd_dsi_csi");
490#endif
491 if (IS_ERR_OR_NULL(dev->reg)) {
492 if (dev->reg == ERR_PTR(-ENODEV)) {
493 dev->reg = NULL;
494 dev_info(&pdev->dev, "%s: no regulator device, overriding\n",
495 __func__);
496 } else {
497 dev_err(&pdev->dev, "%s: couldn't get regulator\n",
498 __func__);
499 return PTR_ERR(dev->reg);
500 }
501 }
502
503 dev->misc_dev.minor = MISC_DYNAMIC_MINOR;
504 dev->misc_dev.name = TEGRA_CAMERA_NAME;
505 dev->misc_dev.fops = &tegra_camera_fops;
506 dev->misc_dev.parent = &pdev->dev;
507
508 err = misc_register(&dev->misc_dev);
509 if (err) {
510 dev_err(&pdev->dev, "%s: Unable to register misc device!\n",
511 TEGRA_CAMERA_NAME);
512 goto misc_register_err;
513 }
514
515 err = tegra_camera_clk_get(pdev, "isp", &dev->isp_clk);
516 if (err)
517 goto misc_register_err;
518 err = tegra_camera_clk_get(pdev, "vi", &dev->vi_clk);
519 if (err)
520 goto vi_clk_get_err;
521 err = tegra_camera_clk_get(pdev, "vi_sensor", &dev->vi_sensor_clk);
522 if (err)
523 goto vi_sensor_clk_get_err;
524 err = tegra_camera_clk_get(pdev, "csus", &dev->csus_clk);
525 if (err)
526 goto csus_clk_get_err;
527 err = tegra_camera_clk_get(pdev, "csi", &dev->csi_clk);
528 if (err)
529 goto csi_clk_get_err;
530 err = tegra_camera_clk_get(pdev, "emc", &dev->emc_clk);
531 if (err)
532 goto emc_clk_get_err;
533
534 /* dev is set in order to restore in _remove */
535 platform_set_drvdata(pdev, dev);
536
537 return 0;
538
539emc_clk_get_err:
540 clk_put(dev->emc_clk);
541csi_clk_get_err:
542 clk_put(dev->csus_clk);
543csus_clk_get_err:
544 clk_put(dev->vi_sensor_clk);
545vi_sensor_clk_get_err:
546 clk_put(dev->vi_clk);
547vi_clk_get_err:
548 clk_put(dev->isp_clk);
549misc_register_err:
550 regulator_put(dev->reg);
551alloc_err:
552 return err;
553}
554
555static int tegra_camera_remove(struct platform_device *pdev)
556{
557 struct tegra_camera_dev *dev = platform_get_drvdata(pdev);
558
559 clk_put(dev->isp_clk);
560 clk_put(dev->vi_clk);
561 clk_put(dev->vi_sensor_clk);
562 clk_put(dev->csus_clk);
563 clk_put(dev->csi_clk);
564
565 misc_deregister(&dev->misc_dev);
566 regulator_put(dev->reg);
567 mutex_destroy(&dev->tegra_camera_lock);
568
569 return 0;
570}
571
572static int tegra_camera_suspend(struct platform_device *pdev, pm_message_t state)
573{
574 struct tegra_camera_dev *dev = platform_get_drvdata(pdev);
575 int ret = 0;
576
577 if (tegra_camera_enabled(dev)) {
578 ret = -EBUSY;
579 dev_err(&pdev->dev,
580 "tegra_camera cannot suspend, "
581 "application is holding on to camera. \n");
582 }
583
584 return ret;
585}
586
587static int tegra_camera_resume(struct platform_device *pdev)
588{
589 return 0;
590}
591
592static struct platform_driver tegra_camera_driver = {
593 .probe = tegra_camera_probe,
594 .remove = tegra_camera_remove,
595 .suspend = tegra_camera_suspend,
596 .resume = tegra_camera_resume,
597 .driver = { .name = TEGRA_CAMERA_NAME }
598};
599
600static int __init tegra_camera_init(void)
601{
602 return platform_driver_register(&tegra_camera_driver);
603}
604
605static void __exit tegra_camera_exit(void)
606{
607 platform_driver_unregister(&tegra_camera_driver);
608}
609
610module_init(tegra_camera_init);
611module_exit(tegra_camera_exit);
612
diff --git a/drivers/media/video/tegra/tegra_dtv.c b/drivers/media/video/tegra/tegra_dtv.c
new file mode 100644
index 00000000000..95270c4c3be
--- /dev/null
+++ b/drivers/media/video/tegra/tegra_dtv.c
@@ -0,0 +1,1089 @@
1/*
2 * tegra_dtv.c - Tegra DTV interface driver
3 *
4 * Author: Adam Jiang <chaoj@nvidia.com>
5 * Copyright (c) 2011, NVIDIA Corporation.
6 * Copyright (c) 2012, NVIDIA Corporation.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/kernel.h>
25#include <linux/io.h>
26#include <linux/clk.h>
27#include <linux/fs.h>
28#include <linux/completion.h>
29#include <linux/dma-mapping.h>
30#include <linux/vmalloc.h>
31#include <linux/slab.h>
32#include <linux/spinlock.h>
33#include <linux/mutex.h>
34#include <linux/workqueue.h>
35#include <linux/wakelock.h>
36#include <linux/platform_device.h>
37#include <linux/miscdevice.h>
38#include <linux/debugfs.h>
39#include <linux/seq_file.h>
40#include <linux/delay.h>
41
42#include <media/tegra_dtv.h>
43
44#include <linux/uaccess.h>
45#include <mach/iomap.h>
46#include <mach/dma.h>
47
48/* offsets from TEGRA_DTV_BASE */
49#define DTV_SPI_CONTROL 0x40
50#define DTV_MODE 0x44
51#define DTV_CTRL 0x48
52#define DTV_PACKET_COUNT 0x4c
53#define DTV_ERROR_COUNT 0x50
54#define DTV_INTERRUPT_STATUS 0x54
55#define DTV_STATUS 0x58
56#define DTV_RX_FIFO 0x5c
57
58/* DTV_SPI_CONTROL */
59#define DTV_SPI_CONTROL_ENABLE_DTV 1
60
61/* DTV_MODE_0 */
62#define DTV_MODE_BYTE_SWIZZLE_SHIFT 6
63#define DTV_MODE_BYTE_SWIZZLE (1 << DTV_MODE_BYTE_SWIZZLE_SHIFT)
64#define DTV_MODE_BIT_SWIZZLE_SHIFT 5
65#define DTV_MODE_BIT_SWIZZLE (1 << DTV_MODE_BIT_SWIZZLE_SHIFT)
66#define DTV_MODE_CLK_EDGE_SHIFT 4
67#define DTV_MODE_CLK_EDGE_MASK 1
68#define DTV_MODE_CLK_EDGE_NEG (1 << DTV_MODE_CLK_EDGE_SHIFT)
69#define DTV_MODE_PRTL_SEL_SHIFT 2
70#define DTV_MODE_PRTL_SEL_MASK (0x3 << DTV_MODE_PRTL_SEL_SHIFT)
71#define DTV_MODE_CLK_MODE_SHIFT 1
72#define DTV_MODE_CLK_MODE_MASK (0x1 << DTV_MODE_CLK_MODE_SHIFT)
73#define DTV_MODE_PRTL_ENABLE 1
74
75/* DTV_CONTROL_0 */
76#define DTV_CTRL_FEC_SIZE_SHIFT 24
77#define DTV_CTRL_FEC_SIZE_MASK (0x7F << DTV_CTRL_FEC_SIZE_SHIFT)
78#define DTV_CTRL_BODY_SIZE_SHIFT 16
79#define DTV_CTRL_BODY_SIZE_MASK (0xFF << DTV_CTRL_BODY_SIZE_SHIFT)
80#define DTV_CTRL_FIFO_ATTN_LEVEL_SHIFT 8
81#define DTV_CTRL_FIFO_ATTN_LEVEL_MASK (0x1F << DTV_CTRL_FIFO_ATTN_LEVEL_SHIFT)
82#define DTV_CTRL_FIFO_ATTN_ONE_WORD (0 << DTV_CTRL_FIFO_ATTN_LEVEL_SHIFT)
83#define DTV_CTRL_FIFO_ATTN_TWO_WORD (1 << DTV_CTRL_FIFO_ATTN_LEVEL_SHIFT)
84#define DTV_CTRL_FIFO_ATTN_THREE_WORD (2 << DTV_CTRL_FIFO_ATTN_LEVEL_SHIFT)
85#define DTV_CTRL_FIFO_ATTN_FOUR_WORD (3 << DTV_CTRL_FIFO_ATTN_LEVEL_SHIFT)
86#define DTV_CTRL_BODY_VALID_SEL_SHIFT 6
87#define DTV_CTRL_BODY_VALID_SEL_MASK (1 << DTV_CTRL_BODY_VALID_SEL_SHIFT)
88#define DTV_CTRL_START_SEL_SHIFT 4
89#define DTV_CTRL_START_SEL_MASK (1 << DTV_CTRL_START_SEL_SHIFT)
90#define DTV_CTRL_ERROR_POLARITY_SHIFT 2
91#define DTV_CTRL_ERROR_POLARITY_MASK (1 << DTV_CTRL_ERROR_POLARITY_SHIFT)
92#define DTV_CTRL_PSYNC_POLARITY_SHIFT 1
93#define DTV_CTRL_PSYNC_POLARITY_MASK (1 << DTV_CTRL_PSYNC_POLARITY_SHIFT)
94#define DTV_CTRL_VALID_POLARITY_SHIFT 0
95#define DTV_CTRL_VALID_POLARITY_MASK (1 << DTV_CTRL_VALID_POLARITY_SHIFT)
96
97/* DTV_INTERRUPT_STATUS_0 */
98#define DTV_INTERRUPT_PACKET_UNDERRUN_ERR 8
99#define DTV_INTERRUPT_BODY_OVERRUN_ERR 4
100#define DTV_INTERRUPT_BODY_UNDERRUN_ERR 2
101#define DTV_INTERRUPT_UPSTREAM_ERR 1
102
103/* DTV_STATUS_0 */
104#define DTV_STATUS_RXF_UNDERRUN 4
105#define DTV_STATUS_RXF_EMPTY 2
106#define DTV_STATUS_RXF_FULL 1
107
108#define TEGRA_DTV_NAME "tegra_dtv"
109
110/* default sw config */
111#define DTV_BUF_SIZE_ORDER PAGE_SHIFT
112#define DTV_MAX_NUM_BUFS 4
113
114#define DTV_FIFO_ATN_LVL_LOW_GEAR 0
115#define DTV_FIFO_ATN_LVL_SECOND_GEAR 1
116#define DTV_FIFO_ATN_LVL_THIRD_GEAR 2
117#define DTV_FIFO_ATN_LVL_TOP_GEAR 3
118
119struct dtv_stream {
120 struct mutex mtx;
121
122 bool xferring; /* is DMA in progress */
123 unsigned num_bufs;
124 void *buffer[DTV_MAX_NUM_BUFS];
125 dma_addr_t buf_phy[DTV_MAX_NUM_BUFS];
126 struct completion comp[DTV_MAX_NUM_BUFS];
127 struct tegra_dma_req dma_req[DTV_MAX_NUM_BUFS];
128 int last_queued;
129
130 int fifo_atn_level;
131
132 struct tegra_dma_channel *dma_chan;
133 bool stopped;
134 struct completion stop_completion;
135 spinlock_t dma_req_lock;
136 size_t buf_size;
137
138 struct work_struct work;
139 struct wake_lock wake_lock;
140 char wake_lock_name[16];
141};
142
143struct tegra_dtv_context {
144 struct tegra_dtv_hw_config config;
145 struct clk *clk;
146 int clk_enabled;
147
148 phys_addr_t phys;
149 void * __iomem base;
150 unsigned long dma_req_sel;
151
152 struct dtv_stream stream;
153 /* debugfs */
154 struct dentry *d;
155 /* for refer back */
156 struct platform_device *pdev;
157 struct miscdevice miscdev;
158};
159
160static inline struct tegra_dtv_context *to_ctx(struct dtv_stream *s)
161{
162 return container_of(s, struct tegra_dtv_context, stream);
163}
164
165/* access control */
166static atomic_t tegra_dtv_instance_nr = ATOMIC_INIT(1);
167
168static inline u32 tegra_dtv_readl(struct tegra_dtv_context *dtv,
169 unsigned long reg)
170{
171 BUG_ON(!dtv->clk_enabled);
172 return readl(dtv->base + reg);
173}
174
175static inline void tegra_dtv_writel(struct tegra_dtv_context *dtv,
176 u32 val, unsigned long reg)
177{
178 BUG_ON(!dtv->clk_enabled);
179 writel(val, dtv->base + reg);
180}
181
182/* process */
183static inline void prevent_suspend(struct dtv_stream *s)
184{
185 pr_debug("%s called.\n", __func__);
186 cancel_work_sync(&s->work);
187 wake_lock(&s->wake_lock);
188}
189
190static void tegra_dtv_worker(struct work_struct *w)
191{
192 struct dtv_stream *s = container_of(w, struct dtv_stream, work);
193 pr_debug("%s called.\n", __func__);
194 wake_unlock(&s->wake_lock);
195}
196
197static inline void wakeup_suspend(struct dtv_stream *s)
198{
199 schedule_work(&s->work);
200}
201
202static inline bool wait_till_stopped(struct dtv_stream *s)
203{
204 int ret;
205
206 pr_debug("%s: wait for completion\n", __func__);
207
208 ret = wait_for_completion_timeout(
209 &s->stop_completion, HZ);
210 if (!ret)
211 pr_err("%s: wait timed out", __func__);
212 if (ret < 0)
213 pr_err("%s: wait error %d\n", __func__, ret);
214
215 wakeup_suspend(s);
216
217 pr_debug("%s: done: %d\n", __func__, ret);
218
219 return true;
220}
221
222/* dma transfer */
223static inline bool are_xfers_pending(struct dtv_stream *s)
224{
225 int i;
226
227 pr_debug("%s called\n", __func__);
228
229 for (i = 0; i < s->num_bufs; i++)
230 if (!completion_done(&s->comp[i]))
231 return true;
232 return false;
233}
234
235static void tegra_dtv_rx_dma_complete(struct tegra_dma_req *req)
236{
237 unsigned long flags;
238 unsigned req_num;
239 struct dtv_stream *s = req->dev;
240
241 spin_lock_irqsave(&s->dma_req_lock, flags);
242
243 pr_debug("%s called.\n", __func__);
244
245 req_num = req - s->dma_req;
246 pr_debug("%s: complete buffer %d size %d bytes\n",
247 __func__, req_num, req->bytes_transferred);
248 BUG_ON(req_num >= s->num_bufs);
249
250 complete(&s->comp[req_num]);
251
252 if (!are_xfers_pending(s))
253 pr_debug("%s: overflow.\n", __func__);
254
255 spin_unlock_irqrestore(&s->dma_req_lock, flags);
256}
257
258/* hw */
259static inline void _dtv_enable_protocol(struct tegra_dtv_context *dtv_ctx)
260{
261 u32 val;
262
263 val = tegra_dtv_readl(dtv_ctx, DTV_MODE);
264 val &= ~0x01;
265 val |= DTV_MODE_PRTL_ENABLE;
266 tegra_dtv_writel(dtv_ctx, val, DTV_MODE);
267}
268
269static inline void _dtv_disable_protocol(struct tegra_dtv_context *dtv_ctx)
270{
271 u32 val;
272
273 val = tegra_dtv_readl(dtv_ctx, DTV_MODE);
274 val &= ~DTV_MODE_PRTL_ENABLE;
275 tegra_dtv_writel(dtv_ctx, val, DTV_MODE);
276}
277
278static inline u32 _dtv_get_status(struct tegra_dtv_context *dtv_ctx)
279{
280 return tegra_dtv_readl(dtv_ctx, DTV_STATUS);
281}
282
283static inline void _dtv_set_attn_level(struct tegra_dtv_context *dtv_ctx)
284{
285 /* TODO: consider have this set to corresponding transfer request */
286 u32 val;
287
288 val = tegra_dtv_readl(dtv_ctx, DTV_CTRL);
289 val &= ~DTV_CTRL_FIFO_ATTN_LEVEL_MASK;
290 val |= DTV_CTRL_FIFO_ATTN_FOUR_WORD;
291 tegra_dtv_writel(dtv_ctx, val, DTV_CTRL);
292}
293
294/* ioctl */
295static inline void _dtv_set_hw_params(struct tegra_dtv_context *dtv_ctx)
296{
297 u32 val = 0;
298 u32 reg;
299 struct tegra_dtv_hw_config *cfg = &dtv_ctx->config;
300
301 val = (cfg->clk_edge << DTV_MODE_CLK_EDGE_SHIFT) |
302 (cfg->protocol_sel << DTV_MODE_PRTL_SEL_SHIFT) |
303 (cfg->clk_mode << DTV_MODE_CLK_MODE_SHIFT);
304 reg = tegra_dtv_readl(dtv_ctx, DTV_MODE);
305 reg &= ~(DTV_MODE_CLK_EDGE_MASK |
306 DTV_MODE_PRTL_SEL_MASK |
307 DTV_MODE_CLK_MODE_MASK);
308 reg |= val;
309 tegra_dtv_writel(dtv_ctx, reg, DTV_MODE);
310
311 val = 0;
312 reg = 0;
313 val = (cfg->fec_size << DTV_CTRL_FEC_SIZE_SHIFT) |
314 (cfg->body_size << DTV_CTRL_BODY_SIZE_SHIFT) |
315 (cfg->body_valid_sel << DTV_CTRL_BODY_VALID_SEL_SHIFT) |
316 (cfg->start_sel << DTV_CTRL_START_SEL_SHIFT) |
317 (cfg->err_pol << DTV_CTRL_ERROR_POLARITY_SHIFT) |
318 (cfg->psync_pol << DTV_CTRL_PSYNC_POLARITY_SHIFT) |
319 (cfg->valid_pol << DTV_CTRL_VALID_POLARITY_SHIFT);
320 reg = tegra_dtv_readl(dtv_ctx, DTV_CTRL);
321 reg &= ~(DTV_CTRL_FEC_SIZE_MASK |
322 DTV_CTRL_BODY_SIZE_MASK |
323 DTV_CTRL_BODY_VALID_SEL_MASK |
324 DTV_CTRL_START_SEL_MASK |
325 DTV_CTRL_ERROR_POLARITY_MASK |
326 DTV_CTRL_PSYNC_POLARITY_MASK |
327 DTV_CTRL_VALID_POLARITY_MASK);
328 reg |= val;
329 tegra_dtv_writel(dtv_ctx, reg, DTV_CTRL);
330}
331
332#define DTV_GET_REG_VAL(x, reg, seg) \
333 ((x & reg##_##seg##_MASK) >> reg##_##seg##_SHIFT)
334
335static inline void _dtv_get_hw_params(struct tegra_dtv_context *dtv_ctx,
336 struct tegra_dtv_hw_config *cfg)
337{
338 u32 reg;
339
340 reg = tegra_dtv_readl(dtv_ctx, DTV_MODE);
341 cfg->clk_edge = DTV_GET_REG_VAL(reg, DTV_MODE, CLK_EDGE);
342 cfg->protocol_sel = DTV_GET_REG_VAL(reg, DTV_MODE, PRTL_SEL);
343 cfg->clk_mode = DTV_GET_REG_VAL(reg, DTV_MODE, CLK_MODE);
344
345 reg = tegra_dtv_readl(dtv_ctx, DTV_CTRL);
346 cfg->fec_size = DTV_GET_REG_VAL(reg, DTV_CTRL, FEC_SIZE);
347 cfg->body_size = DTV_GET_REG_VAL(reg, DTV_CTRL, BODY_SIZE);
348 cfg->body_valid_sel = DTV_GET_REG_VAL(reg, DTV_CTRL, BODY_VALID_SEL);
349 cfg->start_sel = DTV_GET_REG_VAL(reg, DTV_CTRL, START_SEL);
350 cfg->err_pol = DTV_GET_REG_VAL(reg, DTV_CTRL, ERROR_POLARITY);
351 cfg->psync_pol = DTV_GET_REG_VAL(reg, DTV_CTRL, PSYNC_POLARITY);
352 cfg->valid_pol = DTV_GET_REG_VAL(reg, DTV_CTRL, VALID_POLARITY);
353}
354
355/* must call with stream->dma_req_lock held. */
356static int stop_xfer_unsafe(struct dtv_stream *s)
357{
358 int spin = 0;
359 struct tegra_dtv_context *dtv_ctx = to_ctx(s);
360
361 pr_debug("%s called\n", __func__);
362 tegra_dma_cancel(s->dma_chan);
363 _dtv_disable_protocol(dtv_ctx);
364 while ((_dtv_get_status(dtv_ctx) & DTV_STATUS_RXF_FULL) &&
365 spin < 100) {
366 udelay(10);
367 if (spin++ > 50)
368 pr_info("%s : spin %d\n", __func__, spin);
369 }
370 if (spin == 100)
371 pr_warn("%s : spinny\n", __func__);
372
373 return 0;
374}
375
376/* must call with stream->mtx held */
377static void __force_xfer_stop(struct dtv_stream *s)
378{
379 int i;
380
381 pr_debug("%s called.\n", __func__);
382
383 if (!s->stopped) {
384 s->stopped = true;
385 if (are_xfers_pending(s))
386 wait_till_stopped(s);
387 for (i = 0; i < s->num_bufs; i++) {
388 init_completion(&s->comp[i]);
389 complete(&s->comp[i]);
390 }
391 }
392
393 /* just in case. dma should be cancelled before this */
394 if (!tegra_dma_is_empty(s->dma_chan))
395 pr_err("%s: DMA channel is not empty!\n", __func__);
396 tegra_dma_cancel(s->dma_chan);
397 s->xferring = false;
398
399 pr_debug("%s: done\n", __func__);
400}
401
402static long tegra_dtv_ioctl(struct file *file, unsigned int cmd,
403 unsigned long arg)
404{
405 int ret = 0;
406 struct tegra_dtv_context *dtv_ctx;
407 struct dtv_stream *s;
408
409 dtv_ctx = (struct tegra_dtv_context *) file->private_data;
410 s = &dtv_ctx->stream;
411
412 /* process may sleep on this */
413 mutex_lock(&s->mtx);
414
415 switch (cmd) {
416 case TEGRA_DTV_IOCTL_START:
417 pr_debug("%s: run serial ts handling.\n", __func__);
418 s->stopped = false;
419 break;
420 case TEGRA_DTV_IOCTL_STOP:
421 pr_debug("%s: stop serial ts handling.\n", __func__);
422 if (s->xferring) {
423 stop_xfer_unsafe(s);
424 complete(&s->stop_completion);
425 __force_xfer_stop(s);
426 s->stopped = true;
427 }
428 break;
429 case TEGRA_DTV_IOCTL_SET_HW_CONFIG:
430 {
431 struct tegra_dtv_hw_config cfg;
432
433 if (s->xferring) {
434 pr_err("%s: tranfering is in progress.\n", __func__);
435 ret = -EBUSY;
436 break;
437 }
438
439 if (copy_from_user(&cfg, (const void __user *) arg,
440 sizeof(cfg))) {
441 ret = -EFAULT;
442 break;
443 }
444
445 dtv_ctx->config = cfg;
446 _dtv_set_hw_params(dtv_ctx);
447 break;
448 }
449 case TEGRA_DTV_IOCTL_GET_HW_CONFIG:
450 {
451 struct tegra_dtv_hw_config cfg;
452
453 _dtv_get_hw_params(dtv_ctx, &cfg);
454
455 if (copy_to_user((void __user *)arg, &cfg,
456 sizeof(cfg)))
457 ret = -EFAULT;
458 break;
459 }
460 default:
461 ret = -EINVAL;
462 }
463
464 mutex_unlock(&s->mtx);
465
466 return ret;
467}
468
469/* must call with stream->dma_req_lock held. */
470static int start_xfer_unsafe(struct dtv_stream *s, size_t size)
471{
472 int i;
473 u32 reg;
474 struct tegra_dtv_context *dtv_ctx = to_ctx(s);
475
476 BUG_ON(are_xfers_pending(s));
477
478 pr_debug("%s called.\n", __func__);
479
480 for (i = 0; i < s->num_bufs; i++) {
481 init_completion(&s->comp[i]);
482 s->dma_req[i].dest_addr = s->buf_phy[i];
483 s->dma_req[i].size = size;
484 tegra_dma_enqueue_req(s->dma_chan, &s->dma_req[i]);
485 }
486
487 s->last_queued = s->num_bufs - 1;
488
489 /* too late ? */
490 _dtv_set_attn_level(dtv_ctx);
491 _dtv_enable_protocol(dtv_ctx);
492
493 reg = tegra_dtv_readl(dtv_ctx, DTV_MODE);
494 pr_debug("DTV_MODE = 0x%08x\n", reg);
495
496 return 0;
497}
498
499static int try_start_fill_buf(struct dtv_stream *s, size_t size)
500{
501 int ret = 0;
502 unsigned long flags;
503
504 pr_debug("%s called\n", __func__);
505
506 prevent_suspend(s);
507
508 spin_lock_irqsave(&s->dma_req_lock, flags);
509 if (!s->stopped && !are_xfers_pending(s)) {
510 ret = start_xfer_unsafe(s, size);
511 if (ret) {
512 pr_err("%s: start tranfer failed.\n", __func__);
513 /* let process not wait stupid */
514 wakeup_suspend(s);
515 }
516 }
517 spin_unlock_irqrestore(&s->dma_req_lock, flags);
518
519 return ret;
520}
521
522static ssize_t tegra_dtv_read(struct file *file, char __user *buf,
523 size_t size, loff_t *off)
524{
525 ssize_t ret;
526 ssize_t xfer_size = 0;
527 int buf_no;
528 struct tegra_dma_req *req;
529 struct tegra_dtv_context *dtv_ctx;
530
531 dtv_ctx = (struct tegra_dtv_context *) file->private_data;
532
533 mutex_lock(&dtv_ctx->stream.mtx);
534
535 if (!IS_ALIGNED(size, 4) || size < 4 ||
536 size > dtv_ctx->stream.buf_size) {
537 pr_err("%s: invalid user size %d\n", __func__, size);
538 ret = -EINVAL;
539 mutex_unlock(&dtv_ctx->stream.mtx);
540 return ret;
541 }
542
543 pr_debug("%s: read %d bytes.\n", __func__, size);
544
545 if (dtv_ctx->stream.stopped) {
546 pr_debug("%s: tegra dtv transferring is stopped.\n",
547 __func__);
548 ret = 0;
549 mutex_unlock(&dtv_ctx->stream.mtx);
550 return ret;
551 }
552
553 /* start dma transfer */
554 ret = try_start_fill_buf(&dtv_ctx->stream, size);
555 if (ret < 0 && ret != -EALREADY) {
556 pr_err("%s: could not start recording.\n", __func__);
557 mutex_unlock(&dtv_ctx->stream.mtx);
558 return ret;
559 }
560 dtv_ctx->stream.xferring = true;
561
562 buf_no = (dtv_ctx->stream.last_queued + 1) % dtv_ctx->stream.num_bufs;
563 pr_debug("%s: buf_no = %d\n", __func__, buf_no);
564
565 /* Wait for the buffers to be filled up. The maximum timeout
566 *value should be caculated dynamically based on
567 * buf_size(dtv_ctx->stream).buf_size. For isdb-t 1seg signal,
568 *it bit rate is 300 - 456 kpbs, if buf_size = 4096 bytes, then
569 * to fill up one buffer takes ~77ms.
570 */
571 ret = wait_for_completion_interruptible_timeout(
572 &dtv_ctx->stream.comp[buf_no], HZ);
573 if (!ret) {
574 pr_err("%s: timeout", __func__);
575 ret = -ETIMEDOUT;
576 mutex_unlock(&dtv_ctx->stream.mtx);
577 return ret;
578 } else if (ret < 0) {
579 pr_err("%s: wait error %d", __func__, ret);
580 mutex_unlock(&dtv_ctx->stream.mtx);
581 return ret;
582 }
583
584 req = &dtv_ctx->stream.dma_req[buf_no];
585
586 /* xfer cannot exceed buffer size */
587 xfer_size = size > req->size ? req->size : size;
588 req->size = size;
589 dma_sync_single_for_cpu(NULL,
590 dtv_ctx->stream.dma_req[buf_no].dest_addr,
591 dtv_ctx->stream.dma_req[buf_no].size,
592 DMA_FROM_DEVICE);
593 ret = copy_to_user(buf, dtv_ctx->stream.buffer[buf_no], xfer_size);
594 if (ret) {
595 ret = -EFAULT;
596 mutex_unlock(&dtv_ctx->stream.mtx);
597 return ret;
598 }
599
600 /* not stopped, reinitial stop */
601 init_completion(&dtv_ctx->stream.stop_completion);
602
603 dtv_ctx->stream.last_queued = buf_no;
604
605 /* refill copied buffer */
606 ret = tegra_dma_enqueue_req(dtv_ctx->stream.dma_chan, req);
607 BUG_ON(ret);
608
609 ret = xfer_size;
610 *off += xfer_size;
611
612 mutex_unlock(&dtv_ctx->stream.mtx);
613
614 pr_debug("%s : done with ret = %d\n", __func__, ret);
615
616 return ret;
617}
618
619static int tegra_dtv_open(struct inode *inode, struct file *file)
620{
621 int i;
622 struct miscdevice *miscdev = file->private_data;
623 struct tegra_dtv_context *dtv_ctx =
624 container_of(miscdev, struct tegra_dtv_context, miscdev);
625 file->private_data = dtv_ctx;
626
627 dtv_ctx = (struct tegra_dtv_context *) file->private_data;
628
629 pr_debug("%s called\n", __func__);
630
631 /* can be opened once */
632 if (!atomic_dec_and_test(&tegra_dtv_instance_nr)) {
633 atomic_inc(&tegra_dtv_instance_nr);
634 pr_err("tegra_dtv device can only be opened once.\n");
635 return -EBUSY;
636 }
637
638 mutex_lock(&dtv_ctx->stream.mtx);
639
640 dtv_ctx->stream.stopped = false;
641
642 /* cleanup completion */
643 for (i = 0; i < dtv_ctx->stream.num_bufs; i++) {
644 init_completion(&dtv_ctx->stream.comp[i]);
645 /* complete all */
646 complete(&dtv_ctx->stream.comp[i]);
647 }
648
649 mutex_unlock(&dtv_ctx->stream.mtx);
650
651 return 0;
652}
653
654static int tegra_dtv_release(struct inode *inode, struct file *file)
655{
656 struct tegra_dtv_context *dtv_ctx =
657 (struct tegra_dtv_context *) file->private_data;
658
659 pr_debug("%s called\n", __func__);
660
661 atomic_inc(&tegra_dtv_instance_nr);
662
663 mutex_lock(&dtv_ctx->stream.mtx);
664 if (dtv_ctx->stream.xferring) {
665 stop_xfer_unsafe(&dtv_ctx->stream);
666 /* clean up stop condition */
667 complete(&dtv_ctx->stream.stop_completion);
668 __force_xfer_stop(&dtv_ctx->stream);
669 }
670 /* wakeup any pending process */
671 wakeup_suspend(&dtv_ctx->stream);
672 mutex_unlock(&dtv_ctx->stream.mtx);
673
674 pr_debug("%s : done\n", __func__);
675
676 return 0;
677}
678
679static const struct file_operations tegra_dtv_fops = {
680 .owner = THIS_MODULE,
681 .open = tegra_dtv_open,
682 .read = tegra_dtv_read,
683 .unlocked_ioctl = tegra_dtv_ioctl,
684 .release = tegra_dtv_release,
685};
686
687#ifdef CONFIG_DEBUG_FS
688static int dtv_reg_show(struct seq_file *s, void *unused)
689{
690 struct tegra_dtv_context *dtv_ctx = s->private;
691
692 seq_printf(s, "tegra_dtv register list\n");
693 seq_printf(s, "-------------------------------\n");
694 seq_printf(s, "DTV_SPI_CONTROL_0: 0x%08x\n",
695 tegra_dtv_readl(dtv_ctx, DTV_SPI_CONTROL));
696 seq_printf(s, "DTV_MODE_0: 0x%08x\n",
697 tegra_dtv_readl(dtv_ctx, DTV_MODE));
698 seq_printf(s, "DTV_CONTROL: 0x%08x\n",
699 tegra_dtv_readl(dtv_ctx, DTV_CTRL));
700 seq_printf(s, "DTV_FIFO: 0x%08x\n",
701 tegra_dtv_readl(dtv_ctx, DTV_RX_FIFO));
702
703 return 0;
704
705}
706
707static int dtv_debugfs_open(struct inode *inode, struct file *file)
708{
709 return single_open(file, dtv_reg_show, inode->i_private);
710}
711
712static const struct file_operations dtv_debugfs_fops = {
713 .open = dtv_debugfs_open,
714 .read = seq_read,
715 .llseek = seq_lseek,
716 .release = single_release,
717};
718
719static int dtv_debugfs_init(struct tegra_dtv_context *dtv_ctx)
720{
721 struct dentry *d;
722
723 d = debugfs_create_file("tegra_dtv", S_IRUGO, NULL, dtv_ctx,
724 &dtv_debugfs_fops);
725 if (!d)
726 return -ENOMEM;
727
728 dtv_ctx->d = d;
729
730 return 0;
731}
732
733static void dtv_debugfs_exit(struct tegra_dtv_context *dtv_ctx)
734{
735 debugfs_remove(dtv_ctx->d);
736}
737#else
738static int dtv_debugfs_init(struct tegra_dtv_context *dtv_ctx) { return 0; }
739static void dtv_debugfs_exit(struct tegra_dtv_context *dtv_ctx) {};
740#endif
741
742static void setup_dma_rx_request(struct tegra_dma_req *req,
743 struct dtv_stream *s)
744{
745 struct tegra_dtv_context *dtv_ctx;
746
747 pr_debug("%s before to_ctx\n", __func__);
748 dtv_ctx = to_ctx(s);
749
750 pr_debug("%s called\n", __func__);
751
752 memset(req, 0, sizeof(*req));
753
754 req->complete = tegra_dtv_rx_dma_complete;
755 req->dev = s;
756 req->to_memory = true;
757 req->req_sel = TEGRA_DMA_REQ_SEL_DTV;
758
759 req->source_addr = dtv_ctx->phys + DTV_RX_FIFO;
760 req->source_wrap = 4;
761 req->source_bus_width = 32;
762 req->fixed_burst_size = 1;
763
764 req->dest_wrap = 0;
765 req->dest_bus_width = 32;
766}
767
768static int setup_dma(struct tegra_dtv_context *dtv_ctx)
769{
770 int ret = 0;
771 int i;
772
773 pr_debug("%s called\n", __func__);
774
775 for (i = 0; i < dtv_ctx->stream.num_bufs; i++) {
776 dtv_ctx->stream.buf_phy[i] = dma_map_single(
777 &dtv_ctx->pdev->dev,
778 dtv_ctx->stream.buffer[i],
779 dtv_ctx->stream.buf_size,
780 DMA_FROM_DEVICE);
781 BUG_ON(!dtv_ctx->stream.buf_phy[i]);
782 setup_dma_rx_request(&dtv_ctx->stream.dma_req[i],
783 &dtv_ctx->stream);
784 dtv_ctx->stream.dma_req[i].dest_addr =
785 dtv_ctx->stream.buf_phy[i];
786 }
787 dtv_ctx->stream.dma_chan = tegra_dma_allocate_channel(
788 TEGRA_DMA_MODE_CONTINUOUS_SINGLE,
789 "tegra_dtv_rx", dtv_ctx->dma_req_sel);
790 if (!dtv_ctx->stream.dma_chan) {
791 pr_err("%s : cannot allocate input DMA channel: %ld\n",
792 __func__, PTR_ERR(dtv_ctx->stream.dma_chan));
793 ret = -ENODEV;
794 /* release */
795 for (i = 0; i < dtv_ctx->stream.num_bufs; i++) {
796 dma_unmap_single(&dtv_ctx->pdev->dev,
797 dtv_ctx->stream.buf_phy[i],
798 1 << DTV_BUF_SIZE_ORDER,
799 DMA_FROM_DEVICE);
800 dtv_ctx->stream.buf_phy[i] = 0;
801 }
802 tegra_dma_free_channel(dtv_ctx->stream.dma_chan);
803 dtv_ctx->stream.dma_chan = 0;
804
805 return ret;
806 }
807
808 return ret;
809}
810
811static void tear_down_dma(struct tegra_dtv_context *dtv_ctx)
812{
813 int i;
814
815 pr_debug("%s called\n", __func__);
816
817 for (i = 0; i < dtv_ctx->stream.num_bufs; i++) {
818 dma_unmap_single(&dtv_ctx->pdev->dev,
819 dtv_ctx->stream.buf_phy[i],
820 1 << DTV_BUF_SIZE_ORDER,
821 DMA_FROM_DEVICE);
822 dtv_ctx->stream.buf_phy[i] = 0;
823 }
824 tegra_dma_free_channel(dtv_ctx->stream.dma_chan);
825 dtv_ctx->stream.dma_chan = 0;
826}
827
828static int init_stream_buffer(struct dtv_stream *s, unsigned num)
829{
830 int ret;
831 int i, j;
832
833 pr_debug("%s (num %d)\n", __func__, num);
834
835 for (i = 0; i < num; i++) {
836 kfree(s->buffer[i]);
837 s->buffer[i] = kmalloc((1 << DTV_BUF_SIZE_ORDER),
838 GFP_KERNEL | GFP_DMA);
839 if (!s->buffer[i]) {
840 pr_err("%s : cannot allocate buffer.\n", __func__);
841 for (j = i - 1; j >= 0; j--) {
842 kfree(s->buffer[j]);
843 s->buffer[j] = 0;
844 }
845 ret = -ENOMEM;
846 return ret;
847 }
848 }
849 return 0;
850}
851
852static void release_stream_buffer(struct dtv_stream *s, unsigned num)
853{
854 int i;
855
856 pr_debug("%s (num %d)\n", __func__, num);
857
858 for (i = 0; i < num; i++) {
859 kfree(s->buffer[i]);
860 s->buffer[i] = 0;
861 }
862}
863
864static int setup_stream(struct dtv_stream *stream)
865{
866 int ret = 0;
867 int i;
868
869 pr_debug("%s called\n", __func__);
870
871 stream->xferring = false;
872 mutex_init(&stream->mtx);
873 init_completion(&stream->stop_completion);
874 spin_lock_init(&stream->dma_req_lock);
875 stream->dma_chan = NULL;
876 stream->fifo_atn_level = DTV_FIFO_ATN_LVL_TOP_GEAR;
877 stream->buf_size = 1 << DTV_BUF_SIZE_ORDER;
878 stream->num_bufs = DTV_MAX_NUM_BUFS;
879 /* init each buffer */
880 for (i = 0; i < stream->num_bufs; i++) {
881 init_completion(&stream->comp[i]);
882 /* complete all at this moment */
883 complete(&stream->comp[i]);
884 stream->buffer[i] = 0;
885 stream->buf_phy[i] = 0;
886 }
887 stream->last_queued = 0;
888 ret = init_stream_buffer(stream, stream->num_bufs);
889 if (ret < 0)
890 return ret;
891
892 INIT_WORK(&stream->work, tegra_dtv_worker);
893 wake_lock_init(&stream->wake_lock, WAKE_LOCK_SUSPEND, "tegra_dtv");
894
895 return ret;
896}
897
898static int tegra_dtv_probe(struct platform_device *pdev)
899{
900 int ret;
901 struct tegra_dtv_context *dtv_ctx;
902 struct clk *clk;
903 struct resource *res;
904
905 pr_info("%s: probing dtv.\n", __func__);
906
907 dtv_ctx = devm_kzalloc(&pdev->dev, sizeof(struct tegra_dtv_context),
908 GFP_KERNEL);
909 if (!dtv_ctx) {
910 pr_err("%s: Failed to allocate memory for dtv context.\n",
911 __func__);
912 ret = -ENOMEM;
913 return ret;
914 }
915 platform_set_drvdata(pdev, dtv_ctx);
916
917 /* for refer back */
918 dtv_ctx->pdev = pdev;
919
920 /* enable clk for dtv */
921 clk = clk_get(&pdev->dev, NULL);
922 if (!clk) {
923 dev_err(&pdev->dev, "cannot get clock for tegra_dtv.\n");
924 ret = -EIO;
925 goto fail_no_clk;
926 }
927 ret = clk_enable(clk);
928 if (ret < 0) {
929 dev_err(&pdev->dev, "cannot enable clk for tegra_dtv.\n");
930 goto fail_clk_enable;
931 }
932 dtv_ctx->clk_enabled = 1;
933
934 /* get resource */
935 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
936 if (unlikely(!res)) {
937 pr_err("%s: Failed to get resource for dtv.\n",
938 __func__);
939 ret = -ENODEV;
940 goto fail_no_res;
941 }
942
943 if (!devm_request_mem_region(&pdev->dev, res->start,
944 resource_size(res), dev_name(&pdev->dev))) {
945 ret = -EBUSY;
946 return ret;
947 }
948 dtv_ctx->phys = res->start;
949 dtv_ctx->base = devm_ioremap(&pdev->dev, res->start,
950 resource_size(res));
951 if (!dtv_ctx->base) {
952 dev_err(&pdev->dev, "cannot ioremap iomem.\n");
953 ret = -ENOMEM;
954 return ret;
955 }
956
957 ret = setup_stream(&dtv_ctx->stream);
958 if (ret < 0)
959 goto fail_setup_stream;
960
961 ret = setup_dma(dtv_ctx);
962 if (ret < 0)
963 goto fail_setup_dma;
964
965 /* register as a misc device */
966 dtv_ctx->miscdev.minor = MISC_DYNAMIC_MINOR;
967 dtv_ctx->miscdev.name = TEGRA_DTV_NAME;
968 dtv_ctx->miscdev.fops = &tegra_dtv_fops;
969 ret = misc_register(&dtv_ctx->miscdev);
970 if (ret) {
971 pr_err("%s: Unable to register misc device.\n",
972 __func__);
973 ret = -ENODEV;
974 goto fail_misc_reg;
975 }
976
977 ret = dtv_debugfs_init(dtv_ctx);
978 if (ret) {
979 pr_err("%s: Unable to register debugfs entry.\n",
980 __func__);
981 goto fail_debugfs_reg;
982 }
983
984 return 0;
985
986fail_debugfs_reg:
987 dtv_debugfs_exit(dtv_ctx);
988fail_misc_reg:
989 misc_deregister(&dtv_ctx->miscdev);
990fail_setup_stream:
991fail_setup_dma:
992 tear_down_dma(dtv_ctx);
993fail_no_res:
994fail_clk_enable:
995fail_no_clk:
996 if (clk)
997 clk_put(clk);
998
999 return ret;
1000}
1001
1002static int __devexit tegra_dtv_remove(struct platform_device *pdev)
1003{
1004 struct tegra_dtv_context *dtv_ctx;
1005
1006 pr_info("%s: remove dtv.\n", __func__);
1007
1008 dtv_ctx = platform_get_drvdata(pdev);
1009
1010 dtv_debugfs_exit(dtv_ctx);
1011 tear_down_dma(dtv_ctx);
1012 release_stream_buffer(&dtv_ctx->stream, dtv_ctx->stream.num_bufs);
1013
1014 clk_put(dtv_ctx->clk);
1015
1016 misc_deregister(&dtv_ctx->miscdev);
1017
1018 return 0;
1019}
1020
1021#ifdef CONFIG_PM
1022static int tegra_dtv_suspend(struct platform_device *pdev, pm_message_t state)
1023{
1024 struct tegra_dtv_context *dtv_ctx;
1025
1026 pr_info("%s: suspend dtv.\n", __func__);
1027
1028 dtv_ctx = platform_get_drvdata(pdev);
1029
1030 /* stop xferring */
1031 mutex_lock(&dtv_ctx->stream.mtx);
1032 if (dtv_ctx->stream.xferring) {
1033 stop_xfer_unsafe(&dtv_ctx->stream);
1034 /* clean up stop condition */
1035 complete(&dtv_ctx->stream.stop_completion);
1036 __force_xfer_stop(&dtv_ctx->stream);
1037 }
1038 /* wakeup any pending process */
1039 wakeup_suspend(&dtv_ctx->stream);
1040 mutex_unlock(&dtv_ctx->stream.mtx);
1041
1042 clk_disable(dtv_ctx->clk);
1043
1044 return 0;
1045}
1046
1047static int tegra_dtv_resume(struct platform_device *pdev)
1048{
1049 struct tegra_dtv_context *dtv_ctx;
1050
1051 pr_info("%s: resume dtv.\n", __func__);
1052
1053 dtv_ctx = platform_get_drvdata(pdev);
1054 clk_enable(dtv_ctx->clk);
1055
1056 return 0;
1057}
1058#endif /* CONFIG_PM */
1059
1060static struct platform_driver tegra_dtv_driver = {
1061 .driver = {
1062 .name = TEGRA_DTV_NAME,
1063 .owner = THIS_MODULE,
1064 },
1065 .probe = tegra_dtv_probe,
1066 .remove = __devexit_p(tegra_dtv_remove),
1067#ifdef CONFIG_PM
1068 .suspend = tegra_dtv_suspend,
1069 .resume = tegra_dtv_resume,
1070#endif
1071};
1072
1073static int __init tegra_dtv_init(void)
1074{
1075 return platform_driver_register(&tegra_dtv_driver);
1076}
1077
1078static void __exit tegra_dtv_exit(void)
1079{
1080 platform_driver_unregister(&tegra_dtv_driver);
1081}
1082
1083module_init(tegra_dtv_init);
1084module_exit(tegra_dtv_exit);
1085
1086MODULE_AUTHOR("Adam Jiang <chaoj@nvidia.com>");
1087MODULE_DESCRIPTION("Tegra DTV interface driver");
1088MODULE_LICENSE("GPL");
1089MODULE_ALIAS("platform:" TEGRA_DTV_NAME);
diff --git a/drivers/media/video/tegra/tps61050.c b/drivers/media/video/tegra/tps61050.c
new file mode 100644
index 00000000000..def353ca9c1
--- /dev/null
+++ b/drivers/media/video/tegra/tps61050.c
@@ -0,0 +1,991 @@
1/*
2 * tps61050.c - tps61050 flash/torch kernel driver
3 *
4 * Copyright (C) 2011 NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 * 02111-1307, USA
19 */
20
21/* Implementation
22 * --------------
23 * The board level details about the device need to be provided in the board
24 * file with the tps61050_platform_data structure.
25 * Standard among NVC kernel drivers in this structure is:
26 * .cfg = Use the NVC_CFG_ defines that are in nvc_torch.h.
27 * Descriptions of the configuration options are with the defines.
28 * This value is typically 0.
29 * .num = The number of the instance of the device. This should start at 1 and
30 * and increment for each device on the board. This number will be
31 * appended to the MISC driver name, Example: /dev/tps61050.1
32 * .sync = If there is a need to synchronize two devices, then this value is
33 * the number of the device instance this device is allowed to sync to.
34 * This is typically used for stereo applications.
35 * .dev_name = The MISC driver name the device registers as. If not used,
36 * then the part number of the device is used for the driver name.
37 * If using the NVC user driver then use the name found in this
38 * driver under _default_pdata.
39 *
40 * The following is specific to NVC kernel flash/torch drivers:
41 * .pinstate = a pointer to the nvc_torch_pin_state structure. This
42 * structure gives the details of which VI GPIO to use to trigger
43 * the flash. The mask tells which pin and the values is the
44 * level. For example, if VI GPIO pin 6 is used, then
45 * .mask = 0x0040
46 * .values = 0x0040
47 * If VI GPIO pin 0 is used, then
48 * .mask = 0x0001
49 * .values = 0x0001
50 * This is typically just one pin but there is some legacy
51 * here that insinuates more than one pin can be used.
52 * When the flash level is set, then the driver will return the
53 * value in values. When the flash level is off, the driver will
54 * return 0 for the values to deassert the signal.
55 * If a VI GPIO is not used, then the mask and values must be set
56 * to 0. The flash may then be triggered via I2C instead.
57 * However, a VI GPIO is strongly encouraged since it allows
58 * tighter timing with the picture taken as well as reduced power
59 * by asserting the trigger signal for only when needed.
60 * .max_amp_torch = Is the maximum torch value allowed. The value is 0 to
61 * _MAX_TORCH_LEVEL. This is to allow a limit to the amount
62 * of amps used. If left blank then _MAX_TORCH_LEVEL will be
63 * used.
64 * .max_amp_flash = Is the maximum flash value allowed. The value is 0 to
65 * _MAX_FLASH_LEVEL. This is to allow a limit to the amount
66 * of amps used. If left blank then _MAX_FLASH_LEVEL will be
67 * used.
68 *
69 * The following is specific to only this NVC kernel flash/torch driver:
70 * N/A
71 *
72 * Power Requirements
73 * The board power file must contain the following labels for the power
74 * regulator(s) of this device:
75 * "vdd_i2c" = the power regulator for the I2C power.
76 * Note that this device is typically connected directly to the battery rail
77 * and does not need a source power regulator (vdd).
78 *
79 * The above values should be all that is needed to use the device with this
80 * driver. Modifications of this driver should not be needed.
81 */
82
83
84#include <linux/fs.h>
85#include <linux/i2c.h>
86#include <linux/miscdevice.h>
87#include <linux/slab.h>
88#include <linux/delay.h>
89#include <linux/uaccess.h>
90#include <linux/list.h>
91#include <linux/regulator/consumer.h>
92#include <media/nvc.h>
93#include <media/tps61050.h>
94
95#define TPS61050_REG0 0x00
96#define TPS61050_REG1 0x01
97#define TPS61050_REG2 0x02
98#define TPS61050_REG3 0x03
99#define tps61050_flash_cap_size (sizeof(tps61050_flash_cap.numberoflevels) \
100 + (sizeof(tps61050_flash_cap.levels[0]) \
101 * (TPS61050_MAX_FLASH_LEVEL + 1)))
102#define tps61050_torch_cap_size (sizeof(tps61050_torch_cap.numberoflevels) \
103 + (sizeof(tps61050_torch_cap.guidenum[0]) \
104 * (TPS61050_MAX_TORCH_LEVEL + 1)))
105
106
107static struct nvc_torch_flash_capabilities tps61050_flash_cap = {
108 TPS61050_MAX_FLASH_LEVEL + 1,
109 {
110 { 0, 0xFFFFFFFF, 0 },
111 { 150, 558, 2 },
112 { 200, 558, 2 },
113 { 300, 558, 2 },
114 { 400, 558, 2 },
115 { 500, 558, 2 },
116 { 700, 558, 2 },
117 { 900, 558, 2 },
118 { 900, 558, 2 }
119 }
120};
121
122static struct nvc_torch_torch_capabilities tps61050_torch_cap = {
123 TPS61050_MAX_TORCH_LEVEL + 1,
124 {
125 0,
126 50,
127 75,
128 100,
129 150,
130 200,
131 491,
132 491
133 }
134};
135
136struct tps61050_info {
137 atomic_t in_use;
138 struct i2c_client *i2c_client;
139 struct tps61050_platform_data *pdata;
140 struct miscdevice miscdev;
141 struct list_head list;
142 int pwr_api;
143 int pwr_dev;
144 struct nvc_regulator vreg_i2c;
145 u8 s_mode;
146 struct tps61050_info *s_info;
147};
148
149static struct nvc_torch_pin_state tps61050_default_pinstate = {
150 .mask = 0x0000,
151 .values = 0x0000,
152};
153
154static struct tps61050_platform_data tps61050_default_pdata = {
155 .cfg = 0,
156 .num = 0,
157 .sync = 0,
158 .dev_name = "torch",
159 .pinstate = &tps61050_default_pinstate,
160 .max_amp_torch = TPS61050_MAX_TORCH_LEVEL,
161 .max_amp_flash = TPS61050_MAX_FLASH_LEVEL,
162};
163
164static LIST_HEAD(tps61050_info_list);
165static DEFINE_SPINLOCK(tps61050_spinlock);
166
167
168static int tps61050_i2c_rd(struct tps61050_info *info, u8 reg, u8 *val)
169{
170 struct i2c_msg msg[2];
171 u8 buf[2];
172
173 buf[0] = reg;
174 msg[0].addr = info->i2c_client->addr;
175 msg[0].flags = 0;
176 msg[0].len = 1;
177 msg[0].buf = &buf[0];
178 msg[1].addr = info->i2c_client->addr;
179 msg[1].flags = I2C_M_RD;
180 msg[1].len = 1;
181 msg[1].buf = &buf[1];
182 *val = 0;
183 if (i2c_transfer(info->i2c_client->adapter, msg, 2) != 2)
184 return -EIO;
185
186 *val = buf[1];
187 return 0;
188}
189
190static int tps61050_i2c_wr(struct tps61050_info *info, u8 reg, u8 val)
191{
192 struct i2c_msg msg;
193 u8 buf[2];
194
195 buf[0] = reg;
196 buf[1] = val;
197 msg.addr = info->i2c_client->addr;
198 msg.flags = 0;
199 msg.len = 2;
200 msg.buf = &buf[0];
201 if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
202 return -EIO;
203
204 return 0;
205}
206
207static void tps61050_pm_regulator_put(struct nvc_regulator *sreg)
208{
209 regulator_put(sreg->vreg);
210 sreg->vreg = NULL;
211}
212
213static int tps61050_pm_regulator_get(struct tps61050_info *info,
214 struct nvc_regulator *sreg,
215 char vreg_name[])
216{
217 int err = 0;
218
219 sreg->vreg_flag = 0;
220 sreg->vreg = regulator_get(&info->i2c_client->dev, vreg_name);
221 if (IS_ERR_OR_NULL(sreg->vreg)) {
222 dev_err(&info->i2c_client->dev,
223 "%s err for regulator: %s err: %d\n",
224 __func__, vreg_name, (int)sreg->vreg);
225 err = PTR_ERR(sreg->vreg);
226 sreg->vreg = NULL;
227 } else {
228 sreg->vreg_name = vreg_name;
229 dev_dbg(&info->i2c_client->dev,
230 "%s vreg_name: %s\n",
231 __func__, sreg->vreg_name);
232 }
233 return err;
234}
235
236static int tps61050_pm_regulator_en(struct tps61050_info *info,
237 struct nvc_regulator *sreg)
238{
239 int err = 0;
240
241 if (!sreg->vreg_flag && (sreg->vreg != NULL)) {
242 err = regulator_enable(sreg->vreg);
243 if (!err) {
244 dev_dbg(&info->i2c_client->dev,
245 "%s vreg_name: %s\n",
246 __func__, sreg->vreg_name);
247 sreg->vreg_flag = 1;
248 err = 1; /* flag regulator state change */
249 mdelay(5); /* device powerup delay */
250 } else {
251 dev_err(&info->i2c_client->dev,
252 "%s err, regulator: %s\n",
253 __func__, sreg->vreg_name);
254 }
255 }
256 return err;
257}
258
259static int tps61050_pm_regulator_dis(struct tps61050_info *info,
260 struct nvc_regulator *sreg)
261{
262 int err = 0;
263
264 if (sreg->vreg_flag && (sreg->vreg != NULL)) {
265 err = regulator_disable(sreg->vreg);
266 if (!err)
267 dev_dbg(&info->i2c_client->dev,
268 "%s vreg_name: %s\n",
269 __func__, sreg->vreg_name);
270 else
271 dev_err(&info->i2c_client->dev,
272 "%s err, regulator: %s\n",
273 __func__, sreg->vreg_name);
274 }
275 sreg->vreg_flag = 0;
276 return err;
277}
278
279static int tps61050_pm_wr(struct tps61050_info *info, int pwr)
280{
281 int err = 0;
282 u8 reg;
283
284 if (pwr == info->pwr_dev)
285 return 0;
286
287 switch (pwr) {
288 case NVC_PWR_OFF:
289 if ((info->pdata->cfg & NVC_CFG_OFF2STDBY) ||
290 (info->pdata->cfg & NVC_CFG_BOOT_INIT)) {
291 pwr = NVC_PWR_STDBY;
292 } else {
293 err = tps61050_pm_regulator_en(info, &info->vreg_i2c);
294 err |= tps61050_i2c_wr(info, TPS61050_REG0, 0x00);
295 err |= tps61050_i2c_wr(info, TPS61050_REG1, 0x00);
296 err |= tps61050_pm_regulator_dis(info, &info->vreg_i2c);
297 break;
298 }
299 case NVC_PWR_STDBY_OFF:
300 if ((info->pdata->cfg & NVC_CFG_OFF2STDBY) ||
301 (info->pdata->cfg & NVC_CFG_BOOT_INIT)) {
302 pwr = NVC_PWR_STDBY;
303 } else {
304 err = tps61050_pm_regulator_en(info, &info->vreg_i2c);
305 err |= tps61050_i2c_wr(info, TPS61050_REG0, 0x00);
306 err |= tps61050_i2c_wr(info, TPS61050_REG1, 0x00);
307 break;
308 }
309 case NVC_PWR_STDBY:
310 err = tps61050_pm_regulator_en(info, &info->vreg_i2c);
311 err |= tps61050_i2c_rd(info, TPS61050_REG0, &reg);
312 reg &= 0x3F; /* 7:6 = mode */
313 err |= tps61050_i2c_wr(info, TPS61050_REG0, reg);
314 break;
315
316 case NVC_PWR_COMM:
317 case NVC_PWR_ON:
318 err = tps61050_pm_regulator_en(info, &info->vreg_i2c);
319 break;
320
321 default:
322 err = -EINVAL;
323 break;
324 }
325
326 if (err < 0) {
327 dev_err(&info->i2c_client->dev, "%s error\n", __func__);
328 pwr = NVC_PWR_ERR;
329 }
330 info->pwr_dev = pwr;
331 if (err > 0)
332 return 0;
333
334 return err;
335}
336
337static int tps61050_pm_wr_s(struct tps61050_info *info, int pwr)
338{
339 int err1 = 0;
340 int err2 = 0;
341
342 if ((info->s_mode == NVC_SYNC_OFF) ||
343 (info->s_mode == NVC_SYNC_MASTER) ||
344 (info->s_mode == NVC_SYNC_STEREO))
345 err1 = tps61050_pm_wr(info, pwr);
346 if ((info->s_mode == NVC_SYNC_SLAVE) ||
347 (info->s_mode == NVC_SYNC_STEREO))
348 err2 = tps61050_pm_wr(info->s_info, pwr);
349 return err1 | err2;
350}
351
352static int tps61050_pm_api_wr(struct tps61050_info *info, int pwr)
353{
354 int err = 0;
355
356 if (!pwr || (pwr > NVC_PWR_ON))
357 return 0;
358
359 if (pwr > info->pwr_dev)
360 err = tps61050_pm_wr_s(info, pwr);
361 if (!err)
362 info->pwr_api = pwr;
363 else
364 info->pwr_api = NVC_PWR_ERR;
365 if (info->pdata->cfg & NVC_CFG_NOERR)
366 return 0;
367
368 return err;
369}
370
371static int tps61050_pm_dev_wr(struct tps61050_info *info, int pwr)
372{
373 if (pwr < info->pwr_api)
374 pwr = info->pwr_api;
375 return tps61050_pm_wr(info, pwr);
376}
377
378static void tps61050_pm_exit(struct tps61050_info *info)
379{
380 tps61050_pm_wr_s(info, NVC_PWR_OFF);
381 tps61050_pm_regulator_put(&info->vreg_i2c);
382}
383
384static void tps61050_pm_init(struct tps61050_info *info)
385{
386 tps61050_pm_regulator_get(info, &info->vreg_i2c, "vdd_i2c");
387}
388
389struct tps61050_reg_init {
390 u8 mask;
391 u8 val;
392};
393
394static struct tps61050_reg_init tps61050_reg_init_id[] = {
395 {0xC0, 0x00},
396 {0xC0, 0x00},
397 {0x87, 0x00},
398 {0xFF, 0xD1},
399};
400
401static int tps61050_dev_id(struct tps61050_info *info)
402{
403 u8 reg;
404 u8 i;
405 int err;
406
407 tps61050_pm_dev_wr(info, NVC_PWR_COMM);
408 /* There isn't a device ID so we just check that all the registers
409 * equal their startup defaults.
410 */
411 for (i = TPS61050_REG0; i <= TPS61050_REG3; i++) {
412 err = tps61050_i2c_rd(info, i, &reg);
413 if (err) {
414 break;
415 } else {
416 reg &= tps61050_reg_init_id[i].mask;
417 if (reg != tps61050_reg_init_id[i].val) {
418 err = -ENODEV;
419 break;
420 }
421 }
422 }
423 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
424 return err;
425}
426
427static int tps61050_param_rd(struct tps61050_info *info, long arg)
428{
429 struct nvc_param params;
430 struct nvc_torch_pin_state pinstate;
431 const void *data_ptr;
432 u8 reg;
433 u32 data_size = 0;
434 int err;
435
436 if (copy_from_user(&params,
437 (const void __user *)arg,
438 sizeof(struct nvc_param))) {
439 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
440 __func__, __LINE__);
441 return -EINVAL;
442 }
443
444 if (info->s_mode == NVC_SYNC_SLAVE)
445 info = info->s_info;
446 switch (params.param) {
447 case NVC_PARAM_FLASH_CAPS:
448 dev_dbg(&info->i2c_client->dev, "%s FLASH_CAPS\n", __func__);
449 data_ptr = &tps61050_flash_cap;
450 data_size = tps61050_flash_cap_size;
451 break;
452
453 case NVC_PARAM_FLASH_LEVEL:
454 tps61050_pm_dev_wr(info, NVC_PWR_COMM);
455 err = tps61050_i2c_rd(info, TPS61050_REG1, &reg);
456 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
457 if (err < 0)
458 return err;
459
460 if (reg & 0x80) { /* 7:7 flash on/off */
461 reg &= 0x07; /* 2:0 flash setting */
462 reg++; /* flash setting +1 if flash on */
463 } else {
464 reg = 0; /* flash is off */
465 }
466 dev_dbg(&info->i2c_client->dev, "%s FLASH_LEVEL: %u\n",
467 __func__,
468 (unsigned)tps61050_flash_cap.levels[reg].guidenum);
469 data_ptr = &tps61050_flash_cap.levels[reg].guidenum;
470 data_size = sizeof(tps61050_flash_cap.levels[reg].guidenum);
471 break;
472
473 case NVC_PARAM_TORCH_CAPS:
474 dev_dbg(&info->i2c_client->dev, "%s TORCH_CAPS\n", __func__);
475 data_ptr = &tps61050_torch_cap;
476 data_size = tps61050_torch_cap_size;
477 break;
478
479 case NVC_PARAM_TORCH_LEVEL:
480 tps61050_pm_dev_wr(info, NVC_PWR_COMM);
481 err = tps61050_i2c_rd(info, TPS61050_REG0, &reg);
482 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
483 if (err < 0)
484 return err;
485
486 reg &= 0x07;
487 dev_dbg(&info->i2c_client->dev, "%s TORCH_LEVEL: %u\n",
488 __func__,
489 (unsigned)tps61050_torch_cap.guidenum[reg]);
490 data_ptr = &tps61050_torch_cap.guidenum[reg];
491 data_size = sizeof(tps61050_torch_cap.guidenum[reg]);
492 break;
493
494 case NVC_PARAM_FLASH_PIN_STATE:
495 pinstate.mask = info->pdata->pinstate->mask;
496 tps61050_pm_dev_wr(info, NVC_PWR_COMM);
497 err = tps61050_i2c_rd(info, TPS61050_REG1, &reg);
498 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
499 if (err < 0)
500 return err;
501
502 reg &= 0x80; /* 7:7=flash enable */
503 if (reg)
504 /* assert strobe */
505 pinstate.values = info->pdata->pinstate->values;
506 else
507 pinstate.values = 0; /* deassert strobe */
508 dev_dbg(&info->i2c_client->dev, "%s FLASH_PIN_STATE: %x&%x\n",
509 __func__, pinstate.mask, pinstate.values);
510 data_ptr = &pinstate;
511 data_size = sizeof(struct nvc_torch_pin_state);
512 break;
513
514 case NVC_PARAM_STEREO:
515 dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n",
516 __func__, (int)info->s_mode);
517 data_ptr = &info->s_mode;
518 data_size = sizeof(info->s_mode);
519 break;
520
521 default:
522 dev_err(&info->i2c_client->dev,
523 "%s unsupported parameter: %d\n",
524 __func__, params.param);
525 return -EINVAL;
526 }
527
528 if (params.sizeofvalue < data_size) {
529 dev_err(&info->i2c_client->dev,
530 "%s data size mismatch %d != %d\n",
531 __func__, params.sizeofvalue, data_size);
532 return -EINVAL;
533 }
534
535 if (copy_to_user((void __user *)params.p_value,
536 data_ptr,
537 data_size)) {
538 dev_err(&info->i2c_client->dev,
539 "%s copy_to_user err line %d\n",
540 __func__, __LINE__);
541 return -EFAULT;
542 }
543
544 return 0;
545}
546
547static int tps61050_param_wr_s(struct tps61050_info *info,
548 struct nvc_param *params,
549 u8 val)
550{
551 u8 reg;
552 int err = 0;
553
554 /*
555 * 7:6 flash/torch mode
556 * 0 0 = off (power save)
557 * 0 1 = torch only (torch power is 2:0 REG0 where 0 = off)
558 * 1 0 = flash and torch (flash power is 2:0 REG1 (0 is a power level))
559 * 1 1 = N/A
560 * Note that 7:6 of REG0 and REG1 are shadowed with each other.
561 * In the code below we want to turn on/off one
562 * without affecting the other.
563 */
564 switch (params->param) {
565 case NVC_PARAM_FLASH_LEVEL:
566 dev_dbg(&info->i2c_client->dev, "%s FLASH_LEVEL: %d\n",
567 __func__, val);
568 tps61050_pm_dev_wr(info, NVC_PWR_ON);
569 if (val) {
570 val--;
571 if (val > tps61050_default_pdata.max_amp_flash)
572 val = tps61050_default_pdata.max_amp_flash;
573 /* Amp limit values are in the board-sensors file. */
574 if (info->pdata->max_amp_flash &&
575 (val > info->pdata->max_amp_flash))
576 val = info->pdata->max_amp_flash;
577 val |= 0x80; /* 7:7=flash mode */
578 } else {
579 err = tps61050_i2c_rd(info, TPS61050_REG0, &reg);
580 if (reg & 0x07) /* 2:0=torch setting */
581 val = 0x40; /* 6:6 enable just torch */
582 }
583 err |= tps61050_i2c_wr(info, TPS61050_REG1, val);
584 val &= 0xC0; /* 7:6=flash/torch mode */
585 if (!val) /* turn pwr off if no flash && no pwr_api */
586 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
587 return err;
588
589 case NVC_PARAM_TORCH_LEVEL:
590 dev_dbg(&info->i2c_client->dev, "%s TORCH_LEVEL: %d\n",
591 __func__, val);
592 tps61050_pm_dev_wr(info, NVC_PWR_ON);
593 err = tps61050_i2c_rd(info, TPS61050_REG1, &reg);
594 reg &= 0x80; /* 7:7=flash */
595 if (val) {
596 if (val > tps61050_default_pdata.max_amp_torch)
597 val = tps61050_default_pdata.max_amp_torch;
598 /* Amp limit values are in the board-sensors file. */
599 if (info->pdata->max_amp_torch &&
600 (val > info->pdata->max_amp_torch))
601 val = info->pdata->max_amp_torch;
602 if (!reg) /* test if flash/torch off */
603 val |= (0x40); /* 6:6=torch only mode */
604 } else {
605 val |= reg;
606 }
607 err |= tps61050_i2c_wr(info, TPS61050_REG0, val);
608 val &= 0xC0; /* 7:6=mode */
609 if (!val) /* turn pwr off if no torch && no pwr_api */
610 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
611 return err;
612
613 case NVC_PARAM_FLASH_PIN_STATE:
614 dev_dbg(&info->i2c_client->dev, "%s FLASH_PIN_STATE: %d\n",
615 __func__, val);
616 if (val)
617 val = 0x08; /* 3:3=soft trigger */
618 err = tps61050_i2c_rd(info, TPS61050_REG1, &reg);
619 val |= reg;
620 err |= tps61050_i2c_wr(info, TPS61050_REG1, val);
621 return err;
622
623 default:
624 dev_err(&info->i2c_client->dev,
625 "%s unsupported parameter: %d\n",
626 __func__, params->param);
627 return -EINVAL;
628 }
629}
630
631static int tps61050_param_wr(struct tps61050_info *info, long arg)
632{
633 struct nvc_param params;
634 u8 val;
635 int err = 0;
636
637 if (copy_from_user(&params, (const void __user *)arg,
638 sizeof(struct nvc_param))) {
639 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
640 __func__, __LINE__);
641 return -EINVAL;
642 }
643
644 if (copy_from_user(&val, (const void __user *)params.p_value,
645 sizeof(val))) {
646 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
647 __func__, __LINE__);
648 return -EINVAL;
649 }
650
651 /* parameters independent of sync mode */
652 switch (params.param) {
653 case NVC_PARAM_STEREO:
654 dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n",
655 __func__, (int)val);
656 if (val == info->s_mode)
657 return 0;
658
659 switch (val) {
660 case NVC_SYNC_OFF:
661 info->s_mode = val;
662 if (info->s_info != NULL) {
663 info->s_info->s_mode = val;
664 tps61050_pm_wr(info->s_info, NVC_PWR_OFF);
665 }
666 break;
667
668 case NVC_SYNC_MASTER:
669 info->s_mode = val;
670 if (info->s_info != NULL)
671 info->s_info->s_mode = val;
672 break;
673
674 case NVC_SYNC_SLAVE:
675 case NVC_SYNC_STEREO:
676 if (info->s_info != NULL) {
677 /* sync power */
678 info->s_info->pwr_api = info->pwr_api;
679 err = tps61050_pm_wr(info->s_info,
680 info->pwr_dev);
681 if (!err) {
682 info->s_mode = val;
683 info->s_info->s_mode = val;
684 } else {
685 tps61050_pm_wr(info->s_info,
686 NVC_PWR_OFF);
687 err = -EIO;
688 }
689 } else {
690 err = -EINVAL;
691 }
692 break;
693
694 default:
695 err = -EINVAL;
696 }
697 if (info->pdata->cfg & NVC_CFG_NOERR)
698 return 0;
699
700 return err;
701
702 default:
703 /* parameters dependent on sync mode */
704 switch (info->s_mode) {
705 case NVC_SYNC_OFF:
706 case NVC_SYNC_MASTER:
707 return tps61050_param_wr_s(info, &params, val);
708
709 case NVC_SYNC_SLAVE:
710 return tps61050_param_wr_s(info->s_info,
711 &params,
712 val);
713
714 case NVC_SYNC_STEREO:
715 err = tps61050_param_wr_s(info, &params, val);
716 if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX))
717 err |= tps61050_param_wr_s(info->s_info,
718 &params,
719 val);
720 return err;
721
722 default:
723 dev_err(&info->i2c_client->dev, "%s %d internal err\n",
724 __func__, __LINE__);
725 return -EINVAL;
726 }
727 }
728}
729
730static long tps61050_ioctl(struct file *file,
731 unsigned int cmd,
732 unsigned long arg)
733{
734 struct tps61050_info *info = file->private_data;
735 int pwr;
736
737 switch (cmd) {
738 case NVC_IOCTL_PARAM_WR:
739 return tps61050_param_wr(info, arg);
740
741 case NVC_IOCTL_PARAM_RD:
742 return tps61050_param_rd(info, arg);
743
744 case NVC_IOCTL_PWR_WR:
745 /* This is a Guaranteed Level of Service (GLOS) call */
746 pwr = (int)arg * 2;
747 dev_dbg(&info->i2c_client->dev, "%s PWR_WR: %d\n",
748 __func__, pwr);
749 return tps61050_pm_api_wr(info, pwr);
750
751 case NVC_IOCTL_PWR_RD:
752 if (info->s_mode == NVC_SYNC_SLAVE)
753 pwr = info->s_info->pwr_api / 2;
754 else
755 pwr = info->pwr_api / 2;
756 dev_dbg(&info->i2c_client->dev, "%s PWR_RD: %d\n",
757 __func__, pwr);
758 if (copy_to_user((void __user *)arg, (const void *)&pwr,
759 sizeof(pwr))) {
760 dev_err(&info->i2c_client->dev,
761 "%s copy_to_user err line %d\n",
762 __func__, __LINE__);
763 return -EFAULT;
764 }
765 return 0;
766
767 default:
768 dev_err(&info->i2c_client->dev, "%s unsupported ioctl: %x\n",
769 __func__, cmd);
770 return -EINVAL;
771 }
772}
773
774static int tps61050_sync_en(int dev1, int dev2)
775{
776 struct tps61050_info *sync1 = NULL;
777 struct tps61050_info *sync2 = NULL;
778 struct tps61050_info *pos = NULL;
779
780 rcu_read_lock();
781 list_for_each_entry_rcu(pos, &tps61050_info_list, list) {
782 if (pos->pdata->num == dev1) {
783 sync1 = pos;
784 break;
785 }
786 }
787 pos = NULL;
788 list_for_each_entry_rcu(pos, &tps61050_info_list, list) {
789 if (pos->pdata->num == dev2) {
790 sync2 = pos;
791 break;
792 }
793 }
794 rcu_read_unlock();
795 if (sync1 != NULL)
796 sync1->s_info = NULL;
797 if (sync2 != NULL)
798 sync2->s_info = NULL;
799 if (!dev1 && !dev2)
800 return 0; /* no err if default instance 0's used */
801
802 if (dev1 == dev2)
803 return -EINVAL; /* err if sync instance is itself */
804
805 if ((sync1 != NULL) && (sync2 != NULL)) {
806 sync1->s_info = sync2;
807 sync2->s_info = sync1;
808 }
809 return 0;
810}
811
812static int tps61050_sync_dis(struct tps61050_info *info)
813{
814 if (info->s_info != NULL) {
815 info->s_info->s_mode = 0;
816 info->s_info->s_info = NULL;
817 info->s_mode = 0;
818 info->s_info = NULL;
819 return 0;
820 }
821
822 return -EINVAL;
823}
824
825static int tps61050_open(struct inode *inode, struct file *file)
826{
827 struct tps61050_info *info = NULL;
828 struct tps61050_info *pos = NULL;
829 int err;
830
831 rcu_read_lock();
832 list_for_each_entry_rcu(pos, &tps61050_info_list, list) {
833 if (pos->miscdev.minor == iminor(inode)) {
834 info = pos;
835 break;
836 }
837 }
838 rcu_read_unlock();
839 if (!info)
840 return -ENODEV;
841
842 err = tps61050_sync_en(info->pdata->num, info->pdata->sync);
843 if (err == -EINVAL)
844 dev_err(&info->i2c_client->dev,
845 "%s err: invalid num (%u) and sync (%u) instance\n",
846 __func__, info->pdata->num, info->pdata->sync);
847 if (atomic_xchg(&info->in_use, 1))
848 return -EBUSY;
849
850 if (info->s_info != NULL) {
851 if (atomic_xchg(&info->s_info->in_use, 1))
852 return -EBUSY;
853 }
854
855 file->private_data = info;
856 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
857 return 0;
858}
859
860static int tps61050_release(struct inode *inode, struct file *file)
861{
862 struct tps61050_info *info = file->private_data;
863
864 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
865 tps61050_pm_wr_s(info, NVC_PWR_OFF);
866 file->private_data = NULL;
867 WARN_ON(!atomic_xchg(&info->in_use, 0));
868 if (info->s_info != NULL)
869 WARN_ON(!atomic_xchg(&info->s_info->in_use, 0));
870 tps61050_sync_dis(info);
871 return 0;
872}
873
874static const struct file_operations tps61050_fileops = {
875 .owner = THIS_MODULE,
876 .open = tps61050_open,
877 .unlocked_ioctl = tps61050_ioctl,
878 .release = tps61050_release,
879};
880
881static void tps61050_del(struct tps61050_info *info)
882{
883 tps61050_pm_exit(info);
884 tps61050_sync_dis(info);
885 spin_lock(&tps61050_spinlock);
886 list_del_rcu(&info->list);
887 spin_unlock(&tps61050_spinlock);
888 synchronize_rcu();
889}
890
891static int tps61050_remove(struct i2c_client *client)
892{
893 struct tps61050_info *info = i2c_get_clientdata(client);
894
895 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
896 misc_deregister(&info->miscdev);
897 tps61050_del(info);
898 return 0;
899}
900
901static int tps61050_probe(
902 struct i2c_client *client,
903 const struct i2c_device_id *id)
904{
905 struct tps61050_info *info;
906 char dname[16];
907 int err;
908
909 dev_dbg(&client->dev, "%s\n", __func__);
910 info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
911 if (info == NULL) {
912 dev_err(&client->dev, "%s: kzalloc error\n", __func__);
913 return -ENOMEM;
914 }
915
916 info->i2c_client = client;
917 if (client->dev.platform_data) {
918 info->pdata = client->dev.platform_data;
919 } else {
920 info->pdata = &tps61050_default_pdata;
921 dev_dbg(&client->dev,
922 "%s No platform data. Using defaults.\n",
923 __func__);
924 }
925 i2c_set_clientdata(client, info);
926 INIT_LIST_HEAD(&info->list);
927 spin_lock(&tps61050_spinlock);
928 list_add_rcu(&info->list, &tps61050_info_list);
929 spin_unlock(&tps61050_spinlock);
930 tps61050_pm_init(info);
931 err = tps61050_dev_id(info);
932 if (err < 0) {
933 dev_err(&client->dev, "%s device not found\n", __func__);
934 if (info->pdata->cfg & NVC_CFG_NODEV) {
935 tps61050_del(info);
936 return -ENODEV;
937 }
938 } else {
939 dev_dbg(&client->dev, "%s device found\n", __func__);
940 }
941
942 if (info->pdata->dev_name != 0)
943 strcpy(dname, info->pdata->dev_name);
944 else
945 strcpy(dname, "tps61050");
946 if (info->pdata->num)
947 snprintf(dname, sizeof(dname), "%s.%u",
948 dname, info->pdata->num);
949 info->miscdev.name = dname;
950 info->miscdev.fops = &tps61050_fileops;
951 info->miscdev.minor = MISC_DYNAMIC_MINOR;
952 if (misc_register(&info->miscdev)) {
953 dev_err(&client->dev, "%s unable to register misc device %s\n",
954 __func__, dname);
955 tps61050_del(info);
956 return -ENODEV;
957 }
958
959 return 0;
960}
961
962static const struct i2c_device_id tps61050_id[] = {
963 { "tps61050", 0 },
964 { },
965};
966
967MODULE_DEVICE_TABLE(i2c, tps61050_id);
968
969static struct i2c_driver tps61050_i2c_driver = {
970 .driver = {
971 .name = "tps61050",
972 .owner = THIS_MODULE,
973 },
974 .id_table = tps61050_id,
975 .probe = tps61050_probe,
976 .remove = tps61050_remove,
977};
978
979static int __init tps61050_init(void)
980{
981 return i2c_add_driver(&tps61050_i2c_driver);
982}
983
984static void __exit tps61050_exit(void)
985{
986 i2c_del_driver(&tps61050_i2c_driver);
987}
988
989module_init(tps61050_init);
990module_exit(tps61050_exit);
991MODULE_LICENSE("GPL");