1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * tp2855 driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * V0.0X01.0X00 first version.
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #define DEBUG
11*4882a593Smuzhiyun #include <linux/clk.h>
12*4882a593Smuzhiyun #include <linux/device.h>
13*4882a593Smuzhiyun #include <linux/delay.h>
14*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
15*4882a593Smuzhiyun #include <linux/i2c.h>
16*4882a593Smuzhiyun #include <linux/module.h>
17*4882a593Smuzhiyun #include <linux/pm_runtime.h>
18*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
19*4882a593Smuzhiyun #include <linux/sysfs.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <linux/version.h>
22*4882a593Smuzhiyun #include <linux/rk-camera-module.h>
23*4882a593Smuzhiyun #include <media/media-entity.h>
24*4882a593Smuzhiyun #include <media/v4l2-async.h>
25*4882a593Smuzhiyun #include <media/v4l2-ctrls.h>
26*4882a593Smuzhiyun #include <media/v4l2-subdev.h>
27*4882a593Smuzhiyun #include <linux/pinctrl/consumer.h>
28*4882a593Smuzhiyun #include <linux/rk-preisp.h>
29*4882a593Smuzhiyun #include <linux/sched.h>
30*4882a593Smuzhiyun #include <linux/kthread.h>
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #include <sound/core.h>
33*4882a593Smuzhiyun #include <sound/pcm.h>
34*4882a593Smuzhiyun #include <sound/pcm_params.h>
35*4882a593Smuzhiyun #include <sound/soc.h>
36*4882a593Smuzhiyun #include <sound/tlv.h>
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #include <linux/platform_device.h>
39*4882a593Smuzhiyun #include <linux/input.h>
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0)
42*4882a593Smuzhiyun #define TP2855_TEST_PATTERN 0
43*4882a593Smuzhiyun #define TP2855_XVCLK_FREQ 27000000
44*4882a593Smuzhiyun #define TP2855_LINK_FREQ_297M (297000000UL >> 1)
45*4882a593Smuzhiyun #define TP2855_LINK_FREQ_594M (594000000UL >> 1)
46*4882a593Smuzhiyun #define TP2855_LANES 4
47*4882a593Smuzhiyun #define TP2855_BITS_PER_SAMPLE 8
48*4882a593Smuzhiyun #define TP2855_NAME "tp2855"
49*4882a593Smuzhiyun #define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
50*4882a593Smuzhiyun #define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun enum{
53*4882a593Smuzhiyun CH_1=0,
54*4882a593Smuzhiyun CH_2=1,
55*4882a593Smuzhiyun CH_3=2,
56*4882a593Smuzhiyun CH_4=3,
57*4882a593Smuzhiyun CH_ALL=4,
58*4882a593Smuzhiyun MIPI_PAGE=8,
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun enum{
62*4882a593Smuzhiyun STD_TVI, //TVI
63*4882a593Smuzhiyun STD_HDA, //AHD
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun struct regval {
67*4882a593Smuzhiyun u8 addr;
68*4882a593Smuzhiyun u8 val;
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun struct tp2855_mode {
72*4882a593Smuzhiyun u32 bus_fmt;
73*4882a593Smuzhiyun u32 width;
74*4882a593Smuzhiyun u32 height;
75*4882a593Smuzhiyun struct v4l2_fract max_fps;
76*4882a593Smuzhiyun u32 mipi_freq_idx;
77*4882a593Smuzhiyun u32 bpp;
78*4882a593Smuzhiyun const struct regval *global_reg_list;
79*4882a593Smuzhiyun const struct regval *reg_list;
80*4882a593Smuzhiyun u32 hdr_mode;
81*4882a593Smuzhiyun u32 vc[PAD_MAX];
82*4882a593Smuzhiyun u32 channel_reso[PAD_MAX];
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun struct tp2855 {
86*4882a593Smuzhiyun struct i2c_client *client;
87*4882a593Smuzhiyun struct clk *xvclk;
88*4882a593Smuzhiyun struct gpio_desc *reset_gpio;
89*4882a593Smuzhiyun struct gpio_desc *power_gpio;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun struct pinctrl *pinctrl;
92*4882a593Smuzhiyun struct pinctrl_state *pins_default;
93*4882a593Smuzhiyun struct pinctrl_state *pins_sleep;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun struct v4l2_subdev subdev;
96*4882a593Smuzhiyun struct media_pad pad;
97*4882a593Smuzhiyun struct v4l2_ctrl_handler ctrl_handler;
98*4882a593Smuzhiyun struct v4l2_ctrl *pixel_rate;
99*4882a593Smuzhiyun struct v4l2_ctrl *link_freq;
100*4882a593Smuzhiyun struct mutex mutex;
101*4882a593Smuzhiyun bool power_on;
102*4882a593Smuzhiyun struct tp2855_mode *cur_mode;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun u32 module_index;
105*4882a593Smuzhiyun u32 cfg_num;
106*4882a593Smuzhiyun const char *module_facing;
107*4882a593Smuzhiyun const char *module_name;
108*4882a593Smuzhiyun const char *len_name;
109*4882a593Smuzhiyun bool lost_video_status;
110*4882a593Smuzhiyun struct task_struct *detect_thread;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun int streaming;
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun #define to_tp2855(sd) container_of(sd, struct tp2855, subdev)
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun static __maybe_unused const struct regval common_setting_297M_720p_25fps_regs[] = {
119*4882a593Smuzhiyun {0x40, 0x04},
120*4882a593Smuzhiyun {0xf5, 0x00},
121*4882a593Smuzhiyun {0x02, 0x42},
122*4882a593Smuzhiyun {0x07, 0xc0},
123*4882a593Smuzhiyun {0x0b, 0xc0},
124*4882a593Smuzhiyun {0x0c, 0x13},
125*4882a593Smuzhiyun {0x0d, 0x50},
126*4882a593Smuzhiyun {0x15, 0x13},
127*4882a593Smuzhiyun {0x16, 0x15},
128*4882a593Smuzhiyun {0x17, 0x00},
129*4882a593Smuzhiyun {0x18, 0x19},
130*4882a593Smuzhiyun {0x19, 0xd0},
131*4882a593Smuzhiyun {0x1a, 0x25},
132*4882a593Smuzhiyun {0x1c, 0x07},
133*4882a593Smuzhiyun {0x1d, 0xbc},
134*4882a593Smuzhiyun {0x20, 0x30},
135*4882a593Smuzhiyun {0x21, 0x84},
136*4882a593Smuzhiyun {0x22, 0x36},
137*4882a593Smuzhiyun {0x23, 0x3c},
138*4882a593Smuzhiyun #if TP2855_TEST_PATTERN
139*4882a593Smuzhiyun {0x2a, 0x3c}, //vi test
140*4882a593Smuzhiyun #endif
141*4882a593Smuzhiyun {0x2b, 0x60},
142*4882a593Smuzhiyun {0x2c, 0x0a},
143*4882a593Smuzhiyun {0x2d, 0x30},
144*4882a593Smuzhiyun {0x2e, 0x70},
145*4882a593Smuzhiyun {0x30, 0x48},
146*4882a593Smuzhiyun {0x31, 0xbb},
147*4882a593Smuzhiyun {0x32, 0x2e},
148*4882a593Smuzhiyun {0x33, 0x90},
149*4882a593Smuzhiyun {0x35, 0x25},
150*4882a593Smuzhiyun {0x38, 0x00},
151*4882a593Smuzhiyun {0x39, 0x18},
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun {0x40, 0x08},
154*4882a593Smuzhiyun {0x01, 0xf0},
155*4882a593Smuzhiyun {0x02, 0x01},
156*4882a593Smuzhiyun {0x08, 0x0f},
157*4882a593Smuzhiyun {0x20, 0x44},
158*4882a593Smuzhiyun {0x34, 0xe4},
159*4882a593Smuzhiyun {0x14, 0x44},
160*4882a593Smuzhiyun {0x15, 0x0d},
161*4882a593Smuzhiyun {0x25, 0x04},
162*4882a593Smuzhiyun {0x26, 0x03},
163*4882a593Smuzhiyun {0x27, 0x09},
164*4882a593Smuzhiyun {0x29, 0x02},
165*4882a593Smuzhiyun {0x33, 0x07},
166*4882a593Smuzhiyun {0x33, 0x00},
167*4882a593Smuzhiyun {0x14, 0xc4},
168*4882a593Smuzhiyun {0x14, 0x44},
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun // {0x23, 0x02}, //vi test ok
171*4882a593Smuzhiyun // {0x23, 0x00},
172*4882a593Smuzhiyun };
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun static __maybe_unused const struct regval common_setting_594M_1080p_25fps_regs[] = {
175*4882a593Smuzhiyun {0x40, 0x04},
176*4882a593Smuzhiyun {0xf5, 0x00},
177*4882a593Smuzhiyun {0x02, 0x40},
178*4882a593Smuzhiyun {0x07, 0xc0},
179*4882a593Smuzhiyun {0x0b, 0xc0},
180*4882a593Smuzhiyun {0x0c, 0x03},
181*4882a593Smuzhiyun {0x0d, 0x50},
182*4882a593Smuzhiyun {0x15, 0x03},
183*4882a593Smuzhiyun {0x16, 0xd2},
184*4882a593Smuzhiyun {0x17, 0x80},
185*4882a593Smuzhiyun {0x18, 0x29},
186*4882a593Smuzhiyun {0x19, 0x38},
187*4882a593Smuzhiyun {0x1a, 0x47},
188*4882a593Smuzhiyun {0x1c, 0x0a},
189*4882a593Smuzhiyun {0x1d, 0x50},
190*4882a593Smuzhiyun {0x20, 0x30},
191*4882a593Smuzhiyun {0x21, 0x84},
192*4882a593Smuzhiyun {0x22, 0x36},
193*4882a593Smuzhiyun {0x23, 0x3c},
194*4882a593Smuzhiyun #if TP2855_TEST_PATTERN
195*4882a593Smuzhiyun {0x2a, 0x3c}, //vi test
196*4882a593Smuzhiyun #endif
197*4882a593Smuzhiyun {0x2b, 0x60},
198*4882a593Smuzhiyun {0x2c, 0x0a},
199*4882a593Smuzhiyun {0x2d, 0x30},
200*4882a593Smuzhiyun {0x2e, 0x70},
201*4882a593Smuzhiyun {0x30, 0x48},
202*4882a593Smuzhiyun {0x31, 0xbb},
203*4882a593Smuzhiyun {0x32, 0x2e},
204*4882a593Smuzhiyun {0x33, 0x90},
205*4882a593Smuzhiyun {0x35, 0x05},
206*4882a593Smuzhiyun {0x38, 0x00},
207*4882a593Smuzhiyun {0x39, 0x1C},
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun {0x40, 0x08},
210*4882a593Smuzhiyun {0x01, 0xf0},
211*4882a593Smuzhiyun {0x02, 0x01},
212*4882a593Smuzhiyun {0x08, 0x0f},
213*4882a593Smuzhiyun {0x20, 0x44},
214*4882a593Smuzhiyun {0x34, 0xe4},
215*4882a593Smuzhiyun {0x15, 0x0C},
216*4882a593Smuzhiyun {0x25, 0x08},
217*4882a593Smuzhiyun {0x26, 0x06},
218*4882a593Smuzhiyun {0x27, 0x11},
219*4882a593Smuzhiyun {0x29, 0x0a},
220*4882a593Smuzhiyun {0x33, 0x07},
221*4882a593Smuzhiyun {0x33, 0x00},
222*4882a593Smuzhiyun {0x14, 0x33},
223*4882a593Smuzhiyun {0x14, 0xb3},
224*4882a593Smuzhiyun {0x14, 0x33},
225*4882a593Smuzhiyun // {0x23, 0x02}, //vi test ok
226*4882a593Smuzhiyun // {0x23, 0x00},
227*4882a593Smuzhiyun };
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun static struct tp2855_mode supported_modes[] = {
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun .bus_fmt = MEDIA_BUS_FMT_UYVY8_2X8,
232*4882a593Smuzhiyun .width = 1920,
233*4882a593Smuzhiyun .height = 1080,
234*4882a593Smuzhiyun .max_fps = {
235*4882a593Smuzhiyun .numerator = 10000,
236*4882a593Smuzhiyun .denominator = 250000,
237*4882a593Smuzhiyun },
238*4882a593Smuzhiyun .global_reg_list = common_setting_594M_1080p_25fps_regs,
239*4882a593Smuzhiyun .mipi_freq_idx = 0,
240*4882a593Smuzhiyun .bpp = 8,
241*4882a593Smuzhiyun .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
242*4882a593Smuzhiyun .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_1,
243*4882a593Smuzhiyun .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_2,
244*4882a593Smuzhiyun .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_3,
245*4882a593Smuzhiyun },
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun .bus_fmt = MEDIA_BUS_FMT_UYVY8_2X8,
248*4882a593Smuzhiyun .width = 1280,
249*4882a593Smuzhiyun .height = 720,
250*4882a593Smuzhiyun .max_fps = {
251*4882a593Smuzhiyun .numerator = 10000,
252*4882a593Smuzhiyun .denominator = 250000,
253*4882a593Smuzhiyun },
254*4882a593Smuzhiyun .global_reg_list = common_setting_297M_720p_25fps_regs,
255*4882a593Smuzhiyun .mipi_freq_idx = 1,
256*4882a593Smuzhiyun .bpp = 8,
257*4882a593Smuzhiyun .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
258*4882a593Smuzhiyun .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_1,
259*4882a593Smuzhiyun .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_2,
260*4882a593Smuzhiyun .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_3,
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun };
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun static const s64 link_freq_items[] = {
265*4882a593Smuzhiyun TP2855_LINK_FREQ_594M,
266*4882a593Smuzhiyun TP2855_LINK_FREQ_297M,
267*4882a593Smuzhiyun };
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun /* sensor register write */
tp2855_write_reg(struct i2c_client * client,u8 reg,u8 val)270*4882a593Smuzhiyun static int tp2855_write_reg(struct i2c_client *client, u8 reg, u8 val)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun struct i2c_msg msg;
273*4882a593Smuzhiyun u8 buf[2];
274*4882a593Smuzhiyun int ret;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun buf[0] = reg & 0xFF;
277*4882a593Smuzhiyun buf[1] = val;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun msg.addr = client->addr;
280*4882a593Smuzhiyun msg.flags = client->flags;
281*4882a593Smuzhiyun msg.buf = buf;
282*4882a593Smuzhiyun msg.len = sizeof(buf);
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun ret = i2c_transfer(client->adapter, &msg, 1);
285*4882a593Smuzhiyun if (ret >= 0) {
286*4882a593Smuzhiyun usleep_range(300, 400);
287*4882a593Smuzhiyun return 0;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun dev_err(&client->dev,
291*4882a593Smuzhiyun "tp2855 write reg(0x%x val:0x%x) failed !\n", reg, val);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun return ret;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
tp2855_write_array(struct i2c_client * client,const struct regval * regs,int size)296*4882a593Smuzhiyun static int tp2855_write_array(struct i2c_client *client,
297*4882a593Smuzhiyun const struct regval *regs, int size)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun int i, ret = 0;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun i = 0;
302*4882a593Smuzhiyun while (i < size) {
303*4882a593Smuzhiyun ret = tp2855_write_reg(client, regs[i].addr, regs[i].val);
304*4882a593Smuzhiyun if (ret) {
305*4882a593Smuzhiyun dev_err(&client->dev, "%s failed !\n", __func__);
306*4882a593Smuzhiyun break;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun i++;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun return ret;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun /* sensor register read */
tp2855_read_reg(struct i2c_client * client,u8 reg,u8 * val)315*4882a593Smuzhiyun static int tp2855_read_reg(struct i2c_client *client, u8 reg, u8 *val)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun struct i2c_msg msg[2];
318*4882a593Smuzhiyun u8 buf[1];
319*4882a593Smuzhiyun int ret;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun buf[0] = reg & 0xFF;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun msg[0].addr = client->addr;
324*4882a593Smuzhiyun msg[0].flags = client->flags;
325*4882a593Smuzhiyun msg[0].buf = buf;
326*4882a593Smuzhiyun msg[0].len = sizeof(buf);
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun msg[1].addr = client->addr;
329*4882a593Smuzhiyun msg[1].flags = client->flags | I2C_M_RD;
330*4882a593Smuzhiyun msg[1].buf = buf;
331*4882a593Smuzhiyun msg[1].len = 1;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun ret = i2c_transfer(client->adapter, msg, 2);
334*4882a593Smuzhiyun if (ret >= 0) {
335*4882a593Smuzhiyun *val = buf[0];
336*4882a593Smuzhiyun return 0;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun dev_err(&client->dev, "tp2855 read reg(0x%x) failed !\n", reg);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun return ret;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
tp2855_get_reso_dist(const struct tp2855_mode * mode,struct v4l2_mbus_framefmt * framefmt)344*4882a593Smuzhiyun static int tp2855_get_reso_dist(const struct tp2855_mode *mode,
345*4882a593Smuzhiyun struct v4l2_mbus_framefmt *framefmt)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun return abs(mode->width - framefmt->width) +
348*4882a593Smuzhiyun abs(mode->height - framefmt->height);
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun static const struct tp2855_mode *
tp2855_find_best_fit(struct tp2855 * tp2855,struct v4l2_subdev_format * fmt)352*4882a593Smuzhiyun tp2855_find_best_fit(struct tp2855 *tp2855,
353*4882a593Smuzhiyun struct v4l2_subdev_format *fmt)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun struct v4l2_mbus_framefmt *framefmt = &fmt->format;
356*4882a593Smuzhiyun int dist;
357*4882a593Smuzhiyun int cur_best_fit = 0;
358*4882a593Smuzhiyun int cur_best_fit_dist = -1;
359*4882a593Smuzhiyun unsigned int i;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun for (i = 0; i < tp2855->cfg_num; i++) {
362*4882a593Smuzhiyun dist = tp2855_get_reso_dist(&supported_modes[i], framefmt);
363*4882a593Smuzhiyun if ((cur_best_fit_dist == -1 || dist <= cur_best_fit_dist) &&
364*4882a593Smuzhiyun supported_modes[i].bus_fmt == framefmt->code) {
365*4882a593Smuzhiyun cur_best_fit_dist = dist;
366*4882a593Smuzhiyun cur_best_fit = i;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun return &supported_modes[cur_best_fit];
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
tp2855_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)373*4882a593Smuzhiyun static int tp2855_set_fmt(struct v4l2_subdev *sd,
374*4882a593Smuzhiyun struct v4l2_subdev_pad_config *cfg,
375*4882a593Smuzhiyun struct v4l2_subdev_format *fmt)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
378*4882a593Smuzhiyun const struct tp2855_mode *mode;
379*4882a593Smuzhiyun u64 pixel_rate;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun mutex_lock(&tp2855->mutex);
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun mode = tp2855_find_best_fit(tp2855, fmt);
384*4882a593Smuzhiyun fmt->format.code = mode->bus_fmt;
385*4882a593Smuzhiyun fmt->format.width = mode->width;
386*4882a593Smuzhiyun fmt->format.height = mode->height;
387*4882a593Smuzhiyun fmt->format.field = V4L2_FIELD_NONE;
388*4882a593Smuzhiyun fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
391*4882a593Smuzhiyun #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
392*4882a593Smuzhiyun *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
393*4882a593Smuzhiyun #else
394*4882a593Smuzhiyun mutex_unlock(&tp2855->mutex);
395*4882a593Smuzhiyun return -ENOTTY;
396*4882a593Smuzhiyun #endif
397*4882a593Smuzhiyun } else {
398*4882a593Smuzhiyun __v4l2_ctrl_s_ctrl(tp2855->link_freq, mode->mipi_freq_idx);
399*4882a593Smuzhiyun pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * TP2855_LANES;
400*4882a593Smuzhiyun __v4l2_ctrl_s_ctrl_int64(tp2855->pixel_rate, pixel_rate);
401*4882a593Smuzhiyun dev_dbg(&tp2855->client->dev, "mipi_freq_idx %d\n", mode->mipi_freq_idx);
402*4882a593Smuzhiyun dev_dbg(&tp2855->client->dev, "pixel_rate %lld\n", pixel_rate);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun mutex_unlock(&tp2855->mutex);
406*4882a593Smuzhiyun return 0;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
tp2855_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)409*4882a593Smuzhiyun static int tp2855_get_fmt(struct v4l2_subdev *sd,
410*4882a593Smuzhiyun struct v4l2_subdev_pad_config *cfg,
411*4882a593Smuzhiyun struct v4l2_subdev_format *fmt)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
414*4882a593Smuzhiyun struct i2c_client *client = tp2855->client;
415*4882a593Smuzhiyun const struct tp2855_mode *mode = tp2855->cur_mode;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun mutex_lock(&tp2855->mutex);
418*4882a593Smuzhiyun if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
419*4882a593Smuzhiyun #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
420*4882a593Smuzhiyun fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
421*4882a593Smuzhiyun #else
422*4882a593Smuzhiyun mutex_unlock(&tp2855->mutex);
423*4882a593Smuzhiyun return -ENOTTY;
424*4882a593Smuzhiyun #endif
425*4882a593Smuzhiyun } else {
426*4882a593Smuzhiyun fmt->format.width = mode->width;
427*4882a593Smuzhiyun fmt->format.height = mode->height;
428*4882a593Smuzhiyun fmt->format.code = mode->bus_fmt;
429*4882a593Smuzhiyun fmt->format.field = V4L2_FIELD_NONE;
430*4882a593Smuzhiyun if (fmt->pad < PAD_MAX && fmt->pad >= PAD0)
431*4882a593Smuzhiyun fmt->reserved[0] = mode->vc[fmt->pad];
432*4882a593Smuzhiyun else
433*4882a593Smuzhiyun fmt->reserved[0] = mode->vc[PAD0];
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun mutex_unlock(&tp2855->mutex);
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun dev_dbg(&client->dev, "%s: %x %dx%d\n",
438*4882a593Smuzhiyun __func__, fmt->format.code,
439*4882a593Smuzhiyun fmt->format.width, fmt->format.height);
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun return 0;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun
tp2855_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_mbus_code_enum * code)445*4882a593Smuzhiyun static int tp2855_enum_mbus_code(struct v4l2_subdev *sd,
446*4882a593Smuzhiyun struct v4l2_subdev_pad_config *cfg,
447*4882a593Smuzhiyun struct v4l2_subdev_mbus_code_enum *code)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun if (code->index != 0)
452*4882a593Smuzhiyun return -EINVAL;
453*4882a593Smuzhiyun code->code = tp2855->cur_mode->bus_fmt;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun return 0;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
tp2855_enum_frame_sizes(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_frame_size_enum * fse)458*4882a593Smuzhiyun static int tp2855_enum_frame_sizes(struct v4l2_subdev *sd,
459*4882a593Smuzhiyun struct v4l2_subdev_pad_config *cfg,
460*4882a593Smuzhiyun struct v4l2_subdev_frame_size_enum *fse)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
463*4882a593Smuzhiyun struct i2c_client *client = tp2855->client;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun dev_dbg(&client->dev, "%s:\n", __func__);
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun if (fse->index >= tp2855->cfg_num)
468*4882a593Smuzhiyun return -EINVAL;
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun if (fse->code != supported_modes[fse->index].bus_fmt)
471*4882a593Smuzhiyun return -EINVAL;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun fse->min_width = supported_modes[fse->index].width;
474*4882a593Smuzhiyun fse->max_width = supported_modes[fse->index].width;
475*4882a593Smuzhiyun fse->max_height = supported_modes[fse->index].height;
476*4882a593Smuzhiyun fse->min_height = supported_modes[fse->index].height;
477*4882a593Smuzhiyun return 0;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
tp2855_g_mbus_config(struct v4l2_subdev * sd,struct v4l2_mbus_config * cfg)480*4882a593Smuzhiyun static int tp2855_g_mbus_config(struct v4l2_subdev *sd,
481*4882a593Smuzhiyun struct v4l2_mbus_config *cfg)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun cfg->type = V4L2_MBUS_CSI2;
484*4882a593Smuzhiyun cfg->flags = V4L2_MBUS_CSI2_4_LANE |
485*4882a593Smuzhiyun V4L2_MBUS_CSI2_CHANNELS;
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun return 0;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
tp2855_get_module_inf(struct tp2855 * tp2855,struct rkmodule_inf * inf)490*4882a593Smuzhiyun static void tp2855_get_module_inf(struct tp2855 *tp2855,
491*4882a593Smuzhiyun struct rkmodule_inf *inf)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun memset(inf, 0, sizeof(*inf));
494*4882a593Smuzhiyun strlcpy(inf->base.sensor, TP2855_NAME, sizeof(inf->base.sensor));
495*4882a593Smuzhiyun strlcpy(inf->base.module, tp2855->module_name,
496*4882a593Smuzhiyun sizeof(inf->base.module));
497*4882a593Smuzhiyun strlcpy(inf->base.lens, tp2855->len_name, sizeof(inf->base.lens));
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun
tp2855_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)500*4882a593Smuzhiyun static long tp2855_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
503*4882a593Smuzhiyun long ret = 0;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun switch (cmd) {
506*4882a593Smuzhiyun case RKMODULE_GET_MODULE_INFO:
507*4882a593Smuzhiyun tp2855_get_module_inf(tp2855, (struct rkmodule_inf *)arg);
508*4882a593Smuzhiyun break;
509*4882a593Smuzhiyun default:
510*4882a593Smuzhiyun ret = -ENOTTY;
511*4882a593Smuzhiyun break;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun return ret;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
tp2855_compat_ioctl32(struct v4l2_subdev * sd,unsigned int cmd,unsigned long arg)518*4882a593Smuzhiyun static long tp2855_compat_ioctl32(struct v4l2_subdev *sd,
519*4882a593Smuzhiyun unsigned int cmd, unsigned long arg)
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun void __user *up = compat_ptr(arg);
522*4882a593Smuzhiyun struct rkmodule_inf *inf;
523*4882a593Smuzhiyun struct rkmodule_awb_cfg *cfg;
524*4882a593Smuzhiyun long ret = 0;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun switch (cmd) {
527*4882a593Smuzhiyun case RKMODULE_GET_MODULE_INFO:
528*4882a593Smuzhiyun inf = kzalloc(sizeof(*inf), GFP_KERNEL);
529*4882a593Smuzhiyun if (!inf) {
530*4882a593Smuzhiyun ret = -ENOMEM;
531*4882a593Smuzhiyun return ret;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun ret = tp2855_ioctl(sd, cmd, inf);
535*4882a593Smuzhiyun if (!ret)
536*4882a593Smuzhiyun ret = copy_to_user(up, inf, sizeof(*inf));
537*4882a593Smuzhiyun kfree(inf);
538*4882a593Smuzhiyun break;
539*4882a593Smuzhiyun case RKMODULE_AWB_CFG:
540*4882a593Smuzhiyun cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
541*4882a593Smuzhiyun if (!cfg) {
542*4882a593Smuzhiyun ret = -ENOMEM;
543*4882a593Smuzhiyun return ret;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun ret = copy_from_user(cfg, up, sizeof(*cfg));
547*4882a593Smuzhiyun if (!ret)
548*4882a593Smuzhiyun ret = tp2855_ioctl(sd, cmd, cfg);
549*4882a593Smuzhiyun kfree(cfg);
550*4882a593Smuzhiyun break;
551*4882a593Smuzhiyun default:
552*4882a593Smuzhiyun ret = -ENOIOCTLCMD;
553*4882a593Smuzhiyun break;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun return ret;
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun #endif
559*4882a593Smuzhiyun
detect_thread_function(void * data)560*4882a593Smuzhiyun static int detect_thread_function(void *data)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun struct tp2855 *tp2855 = (struct tp2855 *) data;
563*4882a593Smuzhiyun struct i2c_client *client = tp2855->client;
564*4882a593Smuzhiyun u8 detect_status = 0, reg26_val = 0;
565*4882a593Smuzhiyun bool lost_video = false;
566*4882a593Smuzhiyun tp2855->lost_video_status = true;
567*4882a593Smuzhiyun while (!kthread_should_stop()) {
568*4882a593Smuzhiyun if (tp2855->power_on) {
569*4882a593Smuzhiyun tp2855_write_reg(client, 0x40, 0x04);
570*4882a593Smuzhiyun tp2855_read_reg(client, 0x01, &detect_status);
571*4882a593Smuzhiyun tp2855_read_reg(client, 0x26, ®26_val);
572*4882a593Smuzhiyun lost_video = (detect_status & 0x80) ? true : false;
573*4882a593Smuzhiyun if (tp2855->lost_video_status != lost_video) {
574*4882a593Smuzhiyun if (lost_video) {
575*4882a593Smuzhiyun tp2855_write_reg(client, 0x26, (reg26_val & 0xfe));
576*4882a593Smuzhiyun } else {
577*4882a593Smuzhiyun tp2855_write_reg(client, 0x26, (reg26_val | 0x01));
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun tp2855->lost_video_status = lost_video;
580*4882a593Smuzhiyun tp2855_read_reg(client, 0x26, ®26_val);
581*4882a593Smuzhiyun dev_err(&client->dev, "tp2855 detect video lost status %d reg26_val %x\n",
582*4882a593Smuzhiyun lost_video, reg26_val);
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun set_current_state(TASK_INTERRUPTIBLE);
586*4882a593Smuzhiyun schedule_timeout(msecs_to_jiffies(200));
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun return 0;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
detect_thread_start(struct tp2855 * tp2855)591*4882a593Smuzhiyun static int __maybe_unused detect_thread_start(struct tp2855 *tp2855) {
592*4882a593Smuzhiyun int ret = 0;
593*4882a593Smuzhiyun struct i2c_client *client = tp2855->client;
594*4882a593Smuzhiyun tp2855->detect_thread = kthread_create(detect_thread_function,
595*4882a593Smuzhiyun tp2855, "tp2855_kthread");
596*4882a593Smuzhiyun if (IS_ERR(tp2855->detect_thread)) {
597*4882a593Smuzhiyun dev_err(&client->dev, "kthread_create tp2855_kthread failed\n");
598*4882a593Smuzhiyun ret = PTR_ERR(tp2855->detect_thread);
599*4882a593Smuzhiyun tp2855->detect_thread = NULL;
600*4882a593Smuzhiyun return ret;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun wake_up_process(tp2855->detect_thread);
603*4882a593Smuzhiyun return ret;
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun
detect_thread_stop(struct tp2855 * tp2855)606*4882a593Smuzhiyun static int __maybe_unused detect_thread_stop(struct tp2855 *tp2855) {
607*4882a593Smuzhiyun if (tp2855->detect_thread)
608*4882a593Smuzhiyun kthread_stop(tp2855->detect_thread);
609*4882a593Smuzhiyun tp2855->detect_thread = NULL;
610*4882a593Smuzhiyun return 0;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun
__tp2855_start_stream(struct tp2855 * tp2855)613*4882a593Smuzhiyun static int __tp2855_start_stream(struct tp2855 *tp2855)
614*4882a593Smuzhiyun {
615*4882a593Smuzhiyun int ret;
616*4882a593Smuzhiyun int array_size = 0;
617*4882a593Smuzhiyun struct i2c_client *client = tp2855->client;
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun if (tp2855->cur_mode->global_reg_list == common_setting_594M_1080p_25fps_regs) {
620*4882a593Smuzhiyun array_size = ARRAY_SIZE(common_setting_594M_1080p_25fps_regs);
621*4882a593Smuzhiyun } else if (tp2855->cur_mode->global_reg_list == common_setting_297M_720p_25fps_regs) {
622*4882a593Smuzhiyun array_size = ARRAY_SIZE(common_setting_297M_720p_25fps_regs);
623*4882a593Smuzhiyun } else {
624*4882a593Smuzhiyun return -1;
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun ret = tp2855_write_array(tp2855->client,
628*4882a593Smuzhiyun tp2855->cur_mode->global_reg_list, array_size);
629*4882a593Smuzhiyun if (ret) {
630*4882a593Smuzhiyun dev_err(&client->dev, "__tp2855_start_stream global_reg_list faild");
631*4882a593Smuzhiyun return ret;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun detect_thread_start(tp2855);
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun return 0;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
__tp2855_stop_stream(struct tp2855 * tp2855)639*4882a593Smuzhiyun static int __tp2855_stop_stream(struct tp2855 *tp2855)
640*4882a593Smuzhiyun {
641*4882a593Smuzhiyun struct i2c_client *client = tp2855->client;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun tp2855_write_reg(client, 0x40, 0x08);
644*4882a593Smuzhiyun tp2855_write_reg(client, 0x23, 0x02);
645*4882a593Smuzhiyun detect_thread_stop(tp2855);
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun return 0;
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun
tp2855_stream(struct v4l2_subdev * sd,int on)650*4882a593Smuzhiyun static int tp2855_stream(struct v4l2_subdev *sd, int on)
651*4882a593Smuzhiyun {
652*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
653*4882a593Smuzhiyun struct i2c_client *client = tp2855->client;
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun dev_dbg(&client->dev, "s_stream: %d. %dx%d\n", on,
656*4882a593Smuzhiyun tp2855->cur_mode->width,
657*4882a593Smuzhiyun tp2855->cur_mode->height);
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun mutex_lock(&tp2855->mutex);
660*4882a593Smuzhiyun on = !!on;
661*4882a593Smuzhiyun if (tp2855->streaming == on)
662*4882a593Smuzhiyun goto unlock;
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun if (on) {
665*4882a593Smuzhiyun __tp2855_start_stream(tp2855);
666*4882a593Smuzhiyun } else {
667*4882a593Smuzhiyun __tp2855_stop_stream(tp2855);
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun tp2855->streaming = on;
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun unlock:
673*4882a593Smuzhiyun mutex_unlock(&tp2855->mutex);
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun return 0;
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun
tp2855_power(struct v4l2_subdev * sd,int on)678*4882a593Smuzhiyun static int tp2855_power(struct v4l2_subdev *sd, int on)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
681*4882a593Smuzhiyun struct i2c_client *client = tp2855->client;
682*4882a593Smuzhiyun int ret = 0;
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun mutex_lock(&tp2855->mutex);
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun /* If the power state is not modified - no work to do. */
687*4882a593Smuzhiyun if (tp2855->power_on == !!on)
688*4882a593Smuzhiyun goto exit;
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun dev_dbg(&client->dev, "%s: on %d\n", __func__, on);
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun if (on) {
693*4882a593Smuzhiyun ret = pm_runtime_get_sync(&client->dev);
694*4882a593Smuzhiyun if (ret < 0) {
695*4882a593Smuzhiyun pm_runtime_put_noidle(&client->dev);
696*4882a593Smuzhiyun goto exit;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun tp2855->power_on = true;
699*4882a593Smuzhiyun } else {
700*4882a593Smuzhiyun pm_runtime_put(&client->dev);
701*4882a593Smuzhiyun tp2855->power_on = false;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun exit:
705*4882a593Smuzhiyun mutex_unlock(&tp2855->mutex);
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun return ret;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun
__tp2855_power_on(struct tp2855 * tp2855)710*4882a593Smuzhiyun static int __tp2855_power_on(struct tp2855 *tp2855)
711*4882a593Smuzhiyun {
712*4882a593Smuzhiyun int ret;
713*4882a593Smuzhiyun struct device *dev = &tp2855->client->dev;
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun dev_dbg(dev, "%s\n", __func__);
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(tp2855->pins_default)) {
718*4882a593Smuzhiyun ret = pinctrl_select_state(tp2855->pinctrl,
719*4882a593Smuzhiyun tp2855->pins_default);
720*4882a593Smuzhiyun if (ret < 0)
721*4882a593Smuzhiyun dev_err(dev, "could not set pins. ret=%d\n", ret);
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun if (!IS_ERR(tp2855->power_gpio)) {
725*4882a593Smuzhiyun gpiod_set_value_cansleep(tp2855->power_gpio, 1);
726*4882a593Smuzhiyun usleep_range(25*1000, 30*1000);
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun usleep_range(1500, 2000);
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun ret = clk_set_rate(tp2855->xvclk, TP2855_XVCLK_FREQ);
732*4882a593Smuzhiyun if (ret < 0)
733*4882a593Smuzhiyun dev_warn(dev, "Failed to set xvclk rate\n");
734*4882a593Smuzhiyun if (clk_get_rate(tp2855->xvclk) != TP2855_XVCLK_FREQ)
735*4882a593Smuzhiyun dev_warn(dev, "xvclk mismatched\n");
736*4882a593Smuzhiyun ret = clk_prepare_enable(tp2855->xvclk);
737*4882a593Smuzhiyun if (ret < 0) {
738*4882a593Smuzhiyun dev_err(dev, "Failed to enable xvclk\n");
739*4882a593Smuzhiyun goto err_clk;
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun if (!IS_ERR(tp2855->reset_gpio)) {
743*4882a593Smuzhiyun gpiod_set_value_cansleep(tp2855->reset_gpio, 1);
744*4882a593Smuzhiyun usleep_range(10*1000, 20*1000);
745*4882a593Smuzhiyun gpiod_set_value_cansleep(tp2855->reset_gpio, 0);
746*4882a593Smuzhiyun usleep_range(10*1000, 20*1000);
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun usleep_range(10*1000, 20*1000);
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun return 0;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun err_clk:
754*4882a593Smuzhiyun if (!IS_ERR(tp2855->reset_gpio))
755*4882a593Smuzhiyun gpiod_set_value_cansleep(tp2855->reset_gpio, 0);
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(tp2855->pins_sleep))
758*4882a593Smuzhiyun pinctrl_select_state(tp2855->pinctrl, tp2855->pins_sleep);
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun return ret;
761*4882a593Smuzhiyun }
762*4882a593Smuzhiyun
__tp2855_power_off(struct tp2855 * tp2855)763*4882a593Smuzhiyun static void __tp2855_power_off(struct tp2855 *tp2855)
764*4882a593Smuzhiyun {
765*4882a593Smuzhiyun int ret;
766*4882a593Smuzhiyun struct device *dev = &tp2855->client->dev;
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun dev_dbg(dev, "%s\n", __func__);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun if (!IS_ERR(tp2855->reset_gpio))
771*4882a593Smuzhiyun gpiod_set_value_cansleep(tp2855->reset_gpio, 0);
772*4882a593Smuzhiyun clk_disable_unprepare(tp2855->xvclk);
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(tp2855->pins_sleep)) {
775*4882a593Smuzhiyun ret = pinctrl_select_state(tp2855->pinctrl,
776*4882a593Smuzhiyun tp2855->pins_sleep);
777*4882a593Smuzhiyun if (ret < 0)
778*4882a593Smuzhiyun dev_dbg(dev, "could not set pins\n");
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun if (!IS_ERR(tp2855->power_gpio))
782*4882a593Smuzhiyun gpiod_set_value_cansleep(tp2855->power_gpio, 0);
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun
tp2855_initialize_controls(struct tp2855 * tp2855)785*4882a593Smuzhiyun static int tp2855_initialize_controls(struct tp2855 *tp2855)
786*4882a593Smuzhiyun {
787*4882a593Smuzhiyun const struct tp2855_mode *mode;
788*4882a593Smuzhiyun struct v4l2_ctrl_handler *handler;
789*4882a593Smuzhiyun u64 pixel_rate;
790*4882a593Smuzhiyun int ret;
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun handler = &tp2855->ctrl_handler;
793*4882a593Smuzhiyun mode = tp2855->cur_mode;
794*4882a593Smuzhiyun ret = v4l2_ctrl_handler_init(handler, 2);
795*4882a593Smuzhiyun if (ret)
796*4882a593Smuzhiyun return ret;
797*4882a593Smuzhiyun handler->lock = &tp2855->mutex;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun tp2855->link_freq = v4l2_ctrl_new_int_menu(handler, NULL,
800*4882a593Smuzhiyun V4L2_CID_LINK_FREQ,
801*4882a593Smuzhiyun ARRAY_SIZE(link_freq_items) - 1, 0,
802*4882a593Smuzhiyun link_freq_items);
803*4882a593Smuzhiyun __v4l2_ctrl_s_ctrl(tp2855->link_freq, mode->mipi_freq_idx);
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
806*4882a593Smuzhiyun pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * TP2855_LANES;
807*4882a593Smuzhiyun tp2855->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
808*4882a593Smuzhiyun V4L2_CID_PIXEL_RATE, 0, pixel_rate,
809*4882a593Smuzhiyun 1, pixel_rate);
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun if (handler->error) {
813*4882a593Smuzhiyun ret = handler->error;
814*4882a593Smuzhiyun dev_err(&tp2855->client->dev,
815*4882a593Smuzhiyun "Failed to init controls(%d)\n", ret);
816*4882a593Smuzhiyun goto err_free_handler;
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun tp2855->subdev.ctrl_handler = handler;
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun return 0;
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun err_free_handler:
824*4882a593Smuzhiyun v4l2_ctrl_handler_free(handler);
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun return ret;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun
tp2855_runtime_resume(struct device * dev)829*4882a593Smuzhiyun static int tp2855_runtime_resume(struct device *dev)
830*4882a593Smuzhiyun {
831*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
832*4882a593Smuzhiyun struct v4l2_subdev *sd = i2c_get_clientdata(client);
833*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun return __tp2855_power_on(tp2855);
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun
tp2855_runtime_suspend(struct device * dev)838*4882a593Smuzhiyun static int tp2855_runtime_suspend(struct device *dev)
839*4882a593Smuzhiyun {
840*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
841*4882a593Smuzhiyun struct v4l2_subdev *sd = i2c_get_clientdata(client);
842*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun __tp2855_power_off(tp2855);
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun return 0;
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
tp2855_open(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)850*4882a593Smuzhiyun static int tp2855_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
851*4882a593Smuzhiyun {
852*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
853*4882a593Smuzhiyun struct v4l2_mbus_framefmt *try_fmt =
854*4882a593Smuzhiyun v4l2_subdev_get_try_format(sd, fh->pad, 0);
855*4882a593Smuzhiyun const struct tp2855_mode *def_mode = &supported_modes[0];
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun dev_dbg(&tp2855->client->dev, "%s\n", __func__);
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun mutex_lock(&tp2855->mutex);
860*4882a593Smuzhiyun /* Initialize try_fmt */
861*4882a593Smuzhiyun try_fmt->width = def_mode->width;
862*4882a593Smuzhiyun try_fmt->height = def_mode->height;
863*4882a593Smuzhiyun try_fmt->code = def_mode->bus_fmt;
864*4882a593Smuzhiyun try_fmt->field = V4L2_FIELD_NONE;
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun mutex_unlock(&tp2855->mutex);
867*4882a593Smuzhiyun /* No crop or compose */
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun return 0;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun #endif
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
874*4882a593Smuzhiyun static const struct v4l2_subdev_internal_ops tp2855_internal_ops = {
875*4882a593Smuzhiyun .open = tp2855_open,
876*4882a593Smuzhiyun };
877*4882a593Smuzhiyun #endif
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun static const struct v4l2_subdev_video_ops tp2855_video_ops = {
880*4882a593Smuzhiyun .s_stream = tp2855_stream,
881*4882a593Smuzhiyun .g_mbus_config = tp2855_g_mbus_config,
882*4882a593Smuzhiyun };
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun static const struct v4l2_subdev_pad_ops tp2855_subdev_pad_ops = {
885*4882a593Smuzhiyun .enum_mbus_code = tp2855_enum_mbus_code,
886*4882a593Smuzhiyun .enum_frame_size = tp2855_enum_frame_sizes,
887*4882a593Smuzhiyun .get_fmt = tp2855_get_fmt,
888*4882a593Smuzhiyun .set_fmt = tp2855_set_fmt,
889*4882a593Smuzhiyun };
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun static const struct v4l2_subdev_core_ops tp2855_core_ops = {
892*4882a593Smuzhiyun .s_power = tp2855_power,
893*4882a593Smuzhiyun .ioctl = tp2855_ioctl,
894*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
895*4882a593Smuzhiyun .compat_ioctl32 = tp2855_compat_ioctl32,
896*4882a593Smuzhiyun #endif
897*4882a593Smuzhiyun };
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun static const struct v4l2_subdev_ops tp2855_subdev_ops = {
900*4882a593Smuzhiyun .core = &tp2855_core_ops,
901*4882a593Smuzhiyun .video = &tp2855_video_ops,
902*4882a593Smuzhiyun .pad = &tp2855_subdev_pad_ops,
903*4882a593Smuzhiyun };
904*4882a593Smuzhiyun
check_chip_id(struct i2c_client * client)905*4882a593Smuzhiyun static int check_chip_id(struct i2c_client *client){
906*4882a593Smuzhiyun struct device *dev = &client->dev;
907*4882a593Smuzhiyun unsigned char chip_id = 0xFF;
908*4882a593Smuzhiyun tp2855_read_reg(client, 0x34, &chip_id);
909*4882a593Smuzhiyun dev_err(dev, "chip_id : 0x%2x\n", chip_id);
910*4882a593Smuzhiyun if (chip_id != 0x0) {
911*4882a593Smuzhiyun return -1;
912*4882a593Smuzhiyun }
913*4882a593Smuzhiyun return 0;
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun
tp2855_probe(struct i2c_client * client,const struct i2c_device_id * id)916*4882a593Smuzhiyun static int tp2855_probe(struct i2c_client *client,
917*4882a593Smuzhiyun const struct i2c_device_id *id)
918*4882a593Smuzhiyun {
919*4882a593Smuzhiyun struct device *dev = &client->dev;
920*4882a593Smuzhiyun struct device_node *node = dev->of_node;
921*4882a593Smuzhiyun struct tp2855 *tp2855;
922*4882a593Smuzhiyun struct v4l2_subdev *sd;
923*4882a593Smuzhiyun __maybe_unused char facing[2];
924*4882a593Smuzhiyun int ret;
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun dev_info(dev, "driver version: %02x.%02x.%02x",
927*4882a593Smuzhiyun DRIVER_VERSION >> 16,
928*4882a593Smuzhiyun (DRIVER_VERSION & 0xff00) >> 8,
929*4882a593Smuzhiyun DRIVER_VERSION & 0x00ff);
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun tp2855 = devm_kzalloc(dev, sizeof(*tp2855), GFP_KERNEL);
932*4882a593Smuzhiyun if (!tp2855)
933*4882a593Smuzhiyun return -ENOMEM;
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
936*4882a593Smuzhiyun &tp2855->module_index);
937*4882a593Smuzhiyun ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
938*4882a593Smuzhiyun &tp2855->module_facing);
939*4882a593Smuzhiyun ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
940*4882a593Smuzhiyun &tp2855->module_name);
941*4882a593Smuzhiyun ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
942*4882a593Smuzhiyun &tp2855->len_name);
943*4882a593Smuzhiyun if (ret) {
944*4882a593Smuzhiyun dev_err(dev, "could not get %s!\n", RKMODULE_CAMERA_LENS_NAME);
945*4882a593Smuzhiyun return -EINVAL;
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun tp2855->client = client;
949*4882a593Smuzhiyun tp2855->cur_mode = &supported_modes[0];
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun tp2855->xvclk = devm_clk_get(dev, "xvclk");
952*4882a593Smuzhiyun if (IS_ERR(tp2855->xvclk)) {
953*4882a593Smuzhiyun dev_err(dev, "Failed to get xvclk\n");
954*4882a593Smuzhiyun return -EINVAL;
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun tp2855->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
958*4882a593Smuzhiyun if (IS_ERR(tp2855->reset_gpio))
959*4882a593Smuzhiyun dev_warn(dev, "Failed to get reset-gpios\n");
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun tp2855->power_gpio = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW);
962*4882a593Smuzhiyun if (IS_ERR(tp2855->power_gpio))
963*4882a593Smuzhiyun dev_warn(dev, "Failed to get power-gpios\n");
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun tp2855->pinctrl = devm_pinctrl_get(dev);
966*4882a593Smuzhiyun if (!IS_ERR(tp2855->pinctrl)) {
967*4882a593Smuzhiyun tp2855->pins_default =
968*4882a593Smuzhiyun pinctrl_lookup_state(tp2855->pinctrl,
969*4882a593Smuzhiyun OF_CAMERA_PINCTRL_STATE_DEFAULT);
970*4882a593Smuzhiyun if (IS_ERR(tp2855->pins_default))
971*4882a593Smuzhiyun dev_info(dev, "could not get default pinstate\n");
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun tp2855->pins_sleep =
974*4882a593Smuzhiyun pinctrl_lookup_state(tp2855->pinctrl,
975*4882a593Smuzhiyun OF_CAMERA_PINCTRL_STATE_SLEEP);
976*4882a593Smuzhiyun if (IS_ERR(tp2855->pins_sleep))
977*4882a593Smuzhiyun dev_info(dev, "could not get sleep pinstate\n");
978*4882a593Smuzhiyun } else {
979*4882a593Smuzhiyun dev_info(dev, "no pinctrl\n");
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun mutex_init(&tp2855->mutex);
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun sd = &tp2855->subdev;
985*4882a593Smuzhiyun v4l2_i2c_subdev_init(sd, client, &tp2855_subdev_ops);
986*4882a593Smuzhiyun ret = tp2855_initialize_controls(tp2855);
987*4882a593Smuzhiyun if (ret) {
988*4882a593Smuzhiyun dev_err(dev, "Failed to initialize controls tp2855\n");
989*4882a593Smuzhiyun goto err_destroy_mutex;
990*4882a593Smuzhiyun }
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun ret = __tp2855_power_on(tp2855);
993*4882a593Smuzhiyun if (ret) {
994*4882a593Smuzhiyun dev_err(dev, "Failed to power on tp2855\n");
995*4882a593Smuzhiyun goto err_free_handler;
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun ret = check_chip_id(client);
999*4882a593Smuzhiyun if (ret) {
1000*4882a593Smuzhiyun dev_err(dev, "Failed to check senosr id\n");
1001*4882a593Smuzhiyun goto err_free_handler;
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
1005*4882a593Smuzhiyun sd->internal_ops = &tp2855_internal_ops;
1006*4882a593Smuzhiyun sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1007*4882a593Smuzhiyun #endif
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun #if defined(CONFIG_MEDIA_CONTROLLER)
1010*4882a593Smuzhiyun tp2855->pad.flags = MEDIA_PAD_FL_SOURCE;
1011*4882a593Smuzhiyun sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
1012*4882a593Smuzhiyun ret = media_entity_pads_init(&sd->entity, 1, &tp2855->pad);
1013*4882a593Smuzhiyun if (ret < 0)
1014*4882a593Smuzhiyun goto err_power_off;
1015*4882a593Smuzhiyun #endif
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun memset(facing, 0, sizeof(facing));
1018*4882a593Smuzhiyun if (strcmp(tp2855->module_facing, "back") == 0)
1019*4882a593Smuzhiyun facing[0] = 'b';
1020*4882a593Smuzhiyun else
1021*4882a593Smuzhiyun facing[0] = 'f';
1022*4882a593Smuzhiyun
1023*4882a593Smuzhiyun snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
1024*4882a593Smuzhiyun tp2855->module_index, facing,
1025*4882a593Smuzhiyun TP2855_NAME, dev_name(sd->dev));
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun ret = v4l2_async_register_subdev_sensor_common(sd);
1028*4882a593Smuzhiyun if (ret) {
1029*4882a593Smuzhiyun dev_err(dev, "v4l2 async register subdev failed\n");
1030*4882a593Smuzhiyun goto err_clean_entity;
1031*4882a593Smuzhiyun }
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun pm_runtime_set_active(dev);
1034*4882a593Smuzhiyun pm_runtime_enable(dev);
1035*4882a593Smuzhiyun pm_runtime_idle(dev);
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun return 0;
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun err_clean_entity:
1040*4882a593Smuzhiyun #if defined(CONFIG_MEDIA_CONTROLLER)
1041*4882a593Smuzhiyun media_entity_cleanup(&sd->entity);
1042*4882a593Smuzhiyun #endif
1043*4882a593Smuzhiyun err_power_off:
1044*4882a593Smuzhiyun __tp2855_power_off(tp2855);
1045*4882a593Smuzhiyun err_free_handler:
1046*4882a593Smuzhiyun v4l2_ctrl_handler_free(&tp2855->ctrl_handler);
1047*4882a593Smuzhiyun err_destroy_mutex:
1048*4882a593Smuzhiyun mutex_destroy(&tp2855->mutex);
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun return ret;
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun
tp2855_remove(struct i2c_client * client)1053*4882a593Smuzhiyun static int tp2855_remove(struct i2c_client *client)
1054*4882a593Smuzhiyun {
1055*4882a593Smuzhiyun struct v4l2_subdev *sd = i2c_get_clientdata(client);
1056*4882a593Smuzhiyun struct tp2855 *tp2855 = to_tp2855(sd);
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun v4l2_async_unregister_subdev(sd);
1059*4882a593Smuzhiyun #if defined(CONFIG_MEDIA_CONTROLLER)
1060*4882a593Smuzhiyun media_entity_cleanup(&sd->entity);
1061*4882a593Smuzhiyun #endif
1062*4882a593Smuzhiyun v4l2_ctrl_handler_free(&tp2855->ctrl_handler);
1063*4882a593Smuzhiyun mutex_destroy(&tp2855->mutex);
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun pm_runtime_disable(&client->dev);
1066*4882a593Smuzhiyun if (!pm_runtime_status_suspended(&client->dev))
1067*4882a593Smuzhiyun __tp2855_power_off(tp2855);
1068*4882a593Smuzhiyun pm_runtime_set_suspended(&client->dev);
1069*4882a593Smuzhiyun
1070*4882a593Smuzhiyun return 0;
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun static const struct dev_pm_ops tp2855_pm_ops = {
1074*4882a593Smuzhiyun SET_RUNTIME_PM_OPS(tp2855_runtime_suspend,
1075*4882a593Smuzhiyun tp2855_runtime_resume, NULL)
1076*4882a593Smuzhiyun };
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_OF)
1079*4882a593Smuzhiyun static const struct of_device_id tp2855_of_match[] = {
1080*4882a593Smuzhiyun { .compatible = "tp2855" },
1081*4882a593Smuzhiyun {},
1082*4882a593Smuzhiyun };
1083*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, tp2855_of_match);
1084*4882a593Smuzhiyun #endif
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun static const struct i2c_device_id tp2855_match_id[] = {
1087*4882a593Smuzhiyun { "tp2855", 0 },
1088*4882a593Smuzhiyun { },
1089*4882a593Smuzhiyun };
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun static struct i2c_driver tp2855_i2c_driver = {
1092*4882a593Smuzhiyun .driver = {
1093*4882a593Smuzhiyun .name = TP2855_NAME,
1094*4882a593Smuzhiyun .pm = &tp2855_pm_ops,
1095*4882a593Smuzhiyun .of_match_table = of_match_ptr(tp2855_of_match),
1096*4882a593Smuzhiyun },
1097*4882a593Smuzhiyun .probe = &tp2855_probe,
1098*4882a593Smuzhiyun .remove = &tp2855_remove,
1099*4882a593Smuzhiyun .id_table = tp2855_match_id,
1100*4882a593Smuzhiyun };
1101*4882a593Smuzhiyun
sensor_mod_init(void)1102*4882a593Smuzhiyun static int __init sensor_mod_init(void)
1103*4882a593Smuzhiyun {
1104*4882a593Smuzhiyun return i2c_add_driver(&tp2855_i2c_driver);
1105*4882a593Smuzhiyun }
1106*4882a593Smuzhiyun
sensor_mod_exit(void)1107*4882a593Smuzhiyun static void __exit sensor_mod_exit(void)
1108*4882a593Smuzhiyun {
1109*4882a593Smuzhiyun i2c_del_driver(&tp2855_i2c_driver);
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun device_initcall_sync(sensor_mod_init);
1113*4882a593Smuzhiyun module_exit(sensor_mod_exit);
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun MODULE_AUTHOR("Vicent Chi <vicent.chi@rock-chips.com>");
1116*4882a593Smuzhiyun MODULE_DESCRIPTION("tp2855 sensor driver");
1117*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");