media: em28xx: fix spelling mistake, "Cinnergy" -> "Cinergy"
[linux-2.6-block.git] / drivers / media / i2c / adv7180.c
CommitLineData
661521a8 1// SPDX-License-Identifier: GPL-2.0
6789cb52
RR
2/*
3 * adv7180.c Analog Devices ADV7180 video decoder driver
4 * Copyright (c) 2009 Intel Corporation
cccb83f7
VB
5 * Copyright (C) 2013 Cogent Embedded, Inc.
6 * Copyright (C) 2013 Renesas Solutions Corp.
6789cb52 7 */
6789cb52
RR
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/errno.h>
11#include <linux/kernel.h>
12#include <linux/interrupt.h>
13#include <linux/i2c.h>
5a0e3ad6 14#include <linux/slab.h>
250121d3 15#include <linux/of.h>
65d9e14a 16#include <linux/gpio/consumer.h>
6789cb52 17#include <linux/videodev2.h>
937feeed
HV
18#include <media/v4l2-ioctl.h>
19#include <media/v4l2-event.h>
6789cb52 20#include <media/v4l2-device.h>
c9fbeddd 21#include <media/v4l2-ctrls.h>
42752f7a 22#include <linux/mutex.h>
c18818e9 23#include <linux/delay.h>
6789cb52 24
f5dde49b
LPC
25#define ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM 0x0
26#define ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM_PED 0x1
27#define ADV7180_STD_AD_PAL_N_NTSC_J_SECAM 0x2
28#define ADV7180_STD_AD_PAL_N_NTSC_M_SECAM 0x3
29#define ADV7180_STD_NTSC_J 0x4
30#define ADV7180_STD_NTSC_M 0x5
31#define ADV7180_STD_PAL60 0x6
32#define ADV7180_STD_NTSC_443 0x7
33#define ADV7180_STD_PAL_BG 0x8
34#define ADV7180_STD_PAL_N 0x9
35#define ADV7180_STD_PAL_M 0xa
36#define ADV7180_STD_PAL_M_PED 0xb
37#define ADV7180_STD_PAL_COMB_N 0xc
38#define ADV7180_STD_PAL_COMB_N_PED 0xd
39#define ADV7180_STD_PAL_SECAM 0xe
40#define ADV7180_STD_PAL_SECAM_PED 0xf
41
3999e5d0 42#define ADV7180_REG_INPUT_CONTROL 0x0000
bca7ad1a 43#define ADV7180_INPUT_CONTROL_INSEL_MASK 0x0f
d3124294 44
c5ef8f8c
LPC
45#define ADV7182_REG_INPUT_VIDSEL 0x0002
46
ce5d6290 47#define ADV7180_REG_OUTPUT_CONTROL 0x0003
3999e5d0 48#define ADV7180_REG_EXTENDED_OUTPUT_CONTROL 0x0004
42752f7a 49#define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5
6789cb52 50
ce5d6290 51#define ADV7180_REG_AUTODETECT_ENABLE 0x0007
42752f7a 52#define ADV7180_AUTODETECT_DEFAULT 0x7f
c9fbeddd 53/* Contrast */
3999e5d0 54#define ADV7180_REG_CON 0x0008 /*Unsigned */
c9fbeddd
FV
55#define ADV7180_CON_MIN 0
56#define ADV7180_CON_DEF 128
57#define ADV7180_CON_MAX 255
58/* Brightness*/
3999e5d0 59#define ADV7180_REG_BRI 0x000a /*Signed */
c9fbeddd
FV
60#define ADV7180_BRI_MIN -128
61#define ADV7180_BRI_DEF 0
62#define ADV7180_BRI_MAX 127
63/* Hue */
3999e5d0 64#define ADV7180_REG_HUE 0x000b /*Signed, inverted */
c9fbeddd
FV
65#define ADV7180_HUE_MIN -127
66#define ADV7180_HUE_DEF 0
67#define ADV7180_HUE_MAX 128
bca7ad1a 68
3999e5d0 69#define ADV7180_REG_CTRL 0x000e
029d6177 70#define ADV7180_CTRL_IRQ_SPACE 0x20
6789cb52 71
029d6177 72#define ADV7180_REG_PWR_MAN 0x0f
bca7ad1a
FV
73#define ADV7180_PWR_MAN_ON 0x04
74#define ADV7180_PWR_MAN_OFF 0x24
75#define ADV7180_PWR_MAN_RES 0x80
76
3999e5d0 77#define ADV7180_REG_STATUS1 0x0010
d3124294
RR
78#define ADV7180_STATUS1_IN_LOCK 0x01
79#define ADV7180_STATUS1_AUTOD_MASK 0x70
6789cb52
RR
80#define ADV7180_STATUS1_AUTOD_NTSM_M_J 0x00
81#define ADV7180_STATUS1_AUTOD_NTSC_4_43 0x10
82#define ADV7180_STATUS1_AUTOD_PAL_M 0x20
83#define ADV7180_STATUS1_AUTOD_PAL_60 0x30
84#define ADV7180_STATUS1_AUTOD_PAL_B_G 0x40
85#define ADV7180_STATUS1_AUTOD_SECAM 0x50
86#define ADV7180_STATUS1_AUTOD_PAL_COMB 0x60
87#define ADV7180_STATUS1_AUTOD_SECAM_525 0x70
88
3999e5d0 89#define ADV7180_REG_IDENT 0x0011
6789cb52
RR
90#define ADV7180_ID_7180 0x18
91
ce5d6290
SL
92#define ADV7180_REG_STATUS3 0x0013
93#define ADV7180_REG_ANALOG_CLAMP_CTL 0x0014
94#define ADV7180_REG_SHAP_FILTER_CTL_1 0x0017
95#define ADV7180_REG_CTRL_2 0x001d
96#define ADV7180_REG_VSYNC_FIELD_CTL_1 0x0031
97#define ADV7180_REG_MANUAL_WIN_CTL_1 0x003d
98#define ADV7180_REG_MANUAL_WIN_CTL_2 0x003e
99#define ADV7180_REG_MANUAL_WIN_CTL_3 0x003f
100#define ADV7180_REG_LOCK_CNT 0x0051
101#define ADV7180_REG_CVBS_TRIM 0x0052
102#define ADV7180_REG_CLAMP_ADJ 0x005a
103#define ADV7180_REG_RES_CIR 0x005f
104#define ADV7180_REG_DIFF_MODE 0x0060
105
52e37f0a 106#define ADV7180_REG_ICONF1 0x2040
42752f7a
RR
107#define ADV7180_ICONF1_ACTIVE_LOW 0x01
108#define ADV7180_ICONF1_PSYNC_ONLY 0x10
109#define ADV7180_ICONF1_ACTIVE_TO_CLR 0xC0
c9fbeddd 110/* Saturation */
3999e5d0
LPC
111#define ADV7180_REG_SD_SAT_CB 0x00e3 /*Unsigned */
112#define ADV7180_REG_SD_SAT_CR 0x00e4 /*Unsigned */
c9fbeddd
FV
113#define ADV7180_SAT_MIN 0
114#define ADV7180_SAT_DEF 128
115#define ADV7180_SAT_MAX 255
bca7ad1a 116
42752f7a
RR
117#define ADV7180_IRQ1_LOCK 0x01
118#define ADV7180_IRQ1_UNLOCK 0x02
52e37f0a
SL
119#define ADV7180_REG_ISR1 0x2042
120#define ADV7180_REG_ICR1 0x2043
121#define ADV7180_REG_IMR1 0x2044
122#define ADV7180_REG_IMR2 0x2048
42752f7a 123#define ADV7180_IRQ3_AD_CHANGE 0x08
52e37f0a
SL
124#define ADV7180_REG_ISR3 0x204A
125#define ADV7180_REG_ICR3 0x204B
126#define ADV7180_REG_IMR3 0x204C
127#define ADV7180_REG_IMR4 0x2050
6789cb52 128
3999e5d0 129#define ADV7180_REG_NTSC_V_BIT_END 0x00E6
bca7ad1a
FV
130#define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F
131
851a54ef 132#define ADV7180_REG_VPP_SLAVE_ADDR 0xFD
b37135e3
LPC
133#define ADV7180_REG_CSI_SLAVE_ADDR 0xFE
134
ce5d6290
SL
135#define ADV7180_REG_ACE_CTRL1 0x4080
136#define ADV7180_REG_ACE_CTRL5 0x4084
137#define ADV7180_REG_FLCONTROL 0x40e0
08b717c2
LPC
138#define ADV7180_FLCONTROL_FL_ENABLE 0x1
139
ce5d6290
SL
140#define ADV7180_REG_RST_CLAMP 0x809c
141#define ADV7180_REG_AGC_ADJ1 0x80b6
142#define ADV7180_REG_AGC_ADJ2 0x80c0
143
b37135e3
LPC
144#define ADV7180_CSI_REG_PWRDN 0x00
145#define ADV7180_CSI_PWRDN 0x80
146
f5dde49b
LPC
147#define ADV7180_INPUT_CVBS_AIN1 0x00
148#define ADV7180_INPUT_CVBS_AIN2 0x01
149#define ADV7180_INPUT_CVBS_AIN3 0x02
150#define ADV7180_INPUT_CVBS_AIN4 0x03
151#define ADV7180_INPUT_CVBS_AIN5 0x04
152#define ADV7180_INPUT_CVBS_AIN6 0x05
153#define ADV7180_INPUT_SVIDEO_AIN1_AIN2 0x06
154#define ADV7180_INPUT_SVIDEO_AIN3_AIN4 0x07
155#define ADV7180_INPUT_SVIDEO_AIN5_AIN6 0x08
156#define ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3 0x09
157#define ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0a
158
c5ef8f8c
LPC
159#define ADV7182_INPUT_CVBS_AIN1 0x00
160#define ADV7182_INPUT_CVBS_AIN2 0x01
161#define ADV7182_INPUT_CVBS_AIN3 0x02
162#define ADV7182_INPUT_CVBS_AIN4 0x03
163#define ADV7182_INPUT_CVBS_AIN5 0x04
164#define ADV7182_INPUT_CVBS_AIN6 0x05
165#define ADV7182_INPUT_CVBS_AIN7 0x06
166#define ADV7182_INPUT_CVBS_AIN8 0x07
167#define ADV7182_INPUT_SVIDEO_AIN1_AIN2 0x08
168#define ADV7182_INPUT_SVIDEO_AIN3_AIN4 0x09
169#define ADV7182_INPUT_SVIDEO_AIN5_AIN6 0x0a
170#define ADV7182_INPUT_SVIDEO_AIN7_AIN8 0x0b
171#define ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3 0x0c
172#define ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0d
173#define ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2 0x0e
174#define ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4 0x0f
175#define ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6 0x10
176#define ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8 0x11
177
b37135e3 178#define ADV7180_DEFAULT_CSI_I2C_ADDR 0x44
851a54ef 179#define ADV7180_DEFAULT_VPP_I2C_ADDR 0x42
b37135e3 180
08b717c2
LPC
181#define V4L2_CID_ADV_FAST_SWITCH (V4L2_CID_USER_ADV7180_BASE + 0x00)
182
f5dde49b
LPC
183struct adv7180_state;
184
185#define ADV7180_FLAG_RESET_POWERED BIT(0)
bf7dcb80 186#define ADV7180_FLAG_V2 BIT(1)
b37135e3 187#define ADV7180_FLAG_MIPI_CSI2 BIT(2)
851a54ef 188#define ADV7180_FLAG_I2P BIT(3)
f5dde49b
LPC
189
190struct adv7180_chip_info {
191 unsigned int flags;
192 unsigned int valid_input_mask;
193 int (*set_std)(struct adv7180_state *st, unsigned int std);
194 int (*select_input)(struct adv7180_state *st, unsigned int input);
195 int (*init)(struct adv7180_state *state);
196};
197
6789cb52 198struct adv7180_state {
c9fbeddd 199 struct v4l2_ctrl_handler ctrl_hdl;
c277b60a 200 struct v4l2_subdev sd;
d5d51a82 201 struct media_pad pad;
42752f7a
RR
202 struct mutex mutex; /* mutual excl. when accessing chip */
203 int irq;
65d9e14a 204 struct gpio_desc *pwdn_gpio;
c277b60a 205 v4l2_std_id curr_norm;
e246c333 206 bool powered;
937feeed 207 bool streaming;
bca7ad1a 208 u8 input;
3999e5d0
LPC
209
210 struct i2c_client *client;
211 unsigned int register_page;
b37135e3 212 struct i2c_client *csi_client;
851a54ef 213 struct i2c_client *vpp_client;
f5dde49b 214 const struct adv7180_chip_info *chip_info;
851a54ef 215 enum v4l2_field field;
6789cb52 216};
c9fbeddd
FV
217#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \
218 struct adv7180_state, \
219 ctrl_hdl)->sd)
6789cb52 220
3999e5d0
LPC
221static int adv7180_select_page(struct adv7180_state *state, unsigned int page)
222{
223 if (state->register_page != page) {
224 i2c_smbus_write_byte_data(state->client, ADV7180_REG_CTRL,
225 page);
226 state->register_page = page;
227 }
228
229 return 0;
230}
231
232static int adv7180_write(struct adv7180_state *state, unsigned int reg,
233 unsigned int value)
234{
235 lockdep_assert_held(&state->mutex);
236 adv7180_select_page(state, reg >> 8);
237 return i2c_smbus_write_byte_data(state->client, reg & 0xff, value);
238}
239
240static int adv7180_read(struct adv7180_state *state, unsigned int reg)
241{
242 lockdep_assert_held(&state->mutex);
243 adv7180_select_page(state, reg >> 8);
244 return i2c_smbus_read_byte_data(state->client, reg & 0xff);
245}
246
b37135e3
LPC
247static int adv7180_csi_write(struct adv7180_state *state, unsigned int reg,
248 unsigned int value)
249{
250 return i2c_smbus_write_byte_data(state->csi_client, reg, value);
251}
252
f5dde49b
LPC
253static int adv7180_set_video_standard(struct adv7180_state *state,
254 unsigned int std)
255{
256 return state->chip_info->set_std(state, std);
257}
3999e5d0 258
851a54ef
LPC
259static int adv7180_vpp_write(struct adv7180_state *state, unsigned int reg,
260 unsigned int value)
261{
262 return i2c_smbus_write_byte_data(state->vpp_client, reg, value);
263}
264
d3124294 265static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
6789cb52 266{
b294a192
VB
267 /* in case V4L2_IN_ST_NO_SIGNAL */
268 if (!(status1 & ADV7180_STATUS1_IN_LOCK))
269 return V4L2_STD_UNKNOWN;
270
6789cb52
RR
271 switch (status1 & ADV7180_STATUS1_AUTOD_MASK) {
272 case ADV7180_STATUS1_AUTOD_NTSM_M_J:
d3124294 273 return V4L2_STD_NTSC;
6789cb52
RR
274 case ADV7180_STATUS1_AUTOD_NTSC_4_43:
275 return V4L2_STD_NTSC_443;
276 case ADV7180_STATUS1_AUTOD_PAL_M:
277 return V4L2_STD_PAL_M;
278 case ADV7180_STATUS1_AUTOD_PAL_60:
279 return V4L2_STD_PAL_60;
280 case ADV7180_STATUS1_AUTOD_PAL_B_G:
281 return V4L2_STD_PAL;
282 case ADV7180_STATUS1_AUTOD_SECAM:
283 return V4L2_STD_SECAM;
284 case ADV7180_STATUS1_AUTOD_PAL_COMB:
285 return V4L2_STD_PAL_Nc | V4L2_STD_PAL_N;
286 case ADV7180_STATUS1_AUTOD_SECAM_525:
287 return V4L2_STD_SECAM;
288 default:
289 return V4L2_STD_UNKNOWN;
290 }
291}
292
c277b60a
RR
293static int v4l2_std_to_adv7180(v4l2_std_id std)
294{
295 if (std == V4L2_STD_PAL_60)
f5dde49b 296 return ADV7180_STD_PAL60;
c277b60a 297 if (std == V4L2_STD_NTSC_443)
f5dde49b 298 return ADV7180_STD_NTSC_443;
c277b60a 299 if (std == V4L2_STD_PAL_N)
f5dde49b 300 return ADV7180_STD_PAL_N;
c277b60a 301 if (std == V4L2_STD_PAL_M)
f5dde49b 302 return ADV7180_STD_PAL_M;
c277b60a 303 if (std == V4L2_STD_PAL_Nc)
f5dde49b 304 return ADV7180_STD_PAL_COMB_N;
c277b60a
RR
305
306 if (std & V4L2_STD_PAL)
f5dde49b 307 return ADV7180_STD_PAL_BG;
c277b60a 308 if (std & V4L2_STD_NTSC)
f5dde49b 309 return ADV7180_STD_NTSC_M;
c277b60a 310 if (std & V4L2_STD_SECAM)
f5dde49b 311 return ADV7180_STD_PAL_SECAM;
c277b60a
RR
312
313 return -EINVAL;
314}
315
d3124294
RR
316static u32 adv7180_status_to_v4l2(u8 status1)
317{
318 if (!(status1 & ADV7180_STATUS1_IN_LOCK))
319 return V4L2_IN_ST_NO_SIGNAL;
320
321 return 0;
322}
323
3999e5d0 324static int __adv7180_status(struct adv7180_state *state, u32 *status,
bca7ad1a 325 v4l2_std_id *std)
d3124294 326{
3999e5d0 327 int status1 = adv7180_read(state, ADV7180_REG_STATUS1);
d3124294
RR
328
329 if (status1 < 0)
330 return status1;
331
332 if (status)
333 *status = adv7180_status_to_v4l2(status1);
334 if (std)
335 *std = adv7180_std_to_v4l2(status1);
336
337 return 0;
338}
339
6789cb52
RR
340static inline struct adv7180_state *to_state(struct v4l2_subdev *sd)
341{
342 return container_of(sd, struct adv7180_state, sd);
343}
344
345static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
346{
c277b60a 347 struct adv7180_state *state = to_state(sd);
42752f7a
RR
348 int err = mutex_lock_interruptible(&state->mutex);
349 if (err)
350 return err;
c277b60a 351
937feeed
HV
352 if (state->streaming) {
353 err = -EBUSY;
354 goto unlock;
355 }
356
357 err = adv7180_set_video_standard(state,
358 ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM);
359 if (err)
360 goto unlock;
c277b60a 361
937feeed
HV
362 msleep(100);
363 __adv7180_status(state, NULL, std);
364
365 err = v4l2_std_to_adv7180(state->curr_norm);
366 if (err < 0)
367 goto unlock;
368
369 err = adv7180_set_video_standard(state, err);
370
371unlock:
42752f7a 372 mutex_unlock(&state->mutex);
c277b60a 373 return err;
d3124294 374}
6789cb52 375
bca7ad1a
FV
376static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input,
377 u32 output, u32 config)
378{
379 struct adv7180_state *state = to_state(sd);
380 int ret = mutex_lock_interruptible(&state->mutex);
bca7ad1a
FV
381
382 if (ret)
383 return ret;
384
f5dde49b
LPC
385 if (input > 31 || !(BIT(input) & state->chip_info->valid_input_mask)) {
386 ret = -EINVAL;
bca7ad1a 387 goto out;
f5dde49b 388 }
bca7ad1a 389
f5dde49b 390 ret = state->chip_info->select_input(state, input);
bca7ad1a 391
f5dde49b
LPC
392 if (ret == 0)
393 state->input = input;
bca7ad1a
FV
394out:
395 mutex_unlock(&state->mutex);
396 return ret;
397}
398
d3124294
RR
399static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status)
400{
42752f7a
RR
401 struct adv7180_state *state = to_state(sd);
402 int ret = mutex_lock_interruptible(&state->mutex);
403 if (ret)
404 return ret;
405
3999e5d0 406 ret = __adv7180_status(state, status, NULL);
42752f7a
RR
407 mutex_unlock(&state->mutex);
408 return ret;
6789cb52
RR
409}
410
3e35e33c 411static int adv7180_program_std(struct adv7180_state *state)
c277b60a 412{
3e35e33c 413 int ret;
c277b60a 414
937feeed
HV
415 ret = v4l2_std_to_adv7180(state->curr_norm);
416 if (ret < 0)
417 return ret;
3e35e33c 418
937feeed
HV
419 ret = adv7180_set_video_standard(state, ret);
420 if (ret < 0)
421 return ret;
3e35e33c
LPC
422 return 0;
423}
424
425static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
426{
427 struct adv7180_state *state = to_state(sd);
428 int ret = mutex_lock_interruptible(&state->mutex);
429
430 if (ret)
431 return ret;
432
937feeed
HV
433 /* Make sure we can support this std */
434 ret = v4l2_std_to_adv7180(std);
435 if (ret < 0)
436 goto out;
c277b60a 437
937feeed 438 state->curr_norm = std;
3e35e33c
LPC
439
440 ret = adv7180_program_std(state);
c277b60a 441out:
42752f7a 442 mutex_unlock(&state->mutex);
c277b60a
RR
443 return ret;
444}
445
d0fadc86
NS
446static int adv7180_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
447{
448 struct adv7180_state *state = to_state(sd);
449
450 *norm = state->curr_norm;
451
452 return 0;
453}
454
38566d28
NS
455static int adv7180_g_frame_interval(struct v4l2_subdev *sd,
456 struct v4l2_subdev_frame_interval *fi)
457{
458 struct adv7180_state *state = to_state(sd);
459
460 if (state->curr_norm & V4L2_STD_525_60) {
461 fi->interval.numerator = 1001;
462 fi->interval.denominator = 30000;
463 } else {
464 fi->interval.numerator = 1;
465 fi->interval.denominator = 25;
466 }
467
468 return 0;
469}
470
65d9e14a
SL
471static void adv7180_set_power_pin(struct adv7180_state *state, bool on)
472{
473 if (!state->pwdn_gpio)
474 return;
475
476 if (on) {
477 gpiod_set_value_cansleep(state->pwdn_gpio, 0);
478 usleep_range(5000, 10000);
479 } else {
480 gpiod_set_value_cansleep(state->pwdn_gpio, 1);
481 }
482}
483
3999e5d0 484static int adv7180_set_power(struct adv7180_state *state, bool on)
e246c333
LPC
485{
486 u8 val;
b37135e3 487 int ret;
e246c333
LPC
488
489 if (on)
490 val = ADV7180_PWR_MAN_ON;
491 else
492 val = ADV7180_PWR_MAN_OFF;
493
b37135e3
LPC
494 ret = adv7180_write(state, ADV7180_REG_PWR_MAN, val);
495 if (ret)
496 return ret;
497
498 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
499 if (on) {
500 adv7180_csi_write(state, 0xDE, 0x02);
501 adv7180_csi_write(state, 0xD2, 0xF7);
502 adv7180_csi_write(state, 0xD8, 0x65);
503 adv7180_csi_write(state, 0xE0, 0x09);
504 adv7180_csi_write(state, 0x2C, 0x00);
851a54ef
LPC
505 if (state->field == V4L2_FIELD_NONE)
506 adv7180_csi_write(state, 0x1D, 0x80);
b37135e3
LPC
507 adv7180_csi_write(state, 0x00, 0x00);
508 } else {
509 adv7180_csi_write(state, 0x00, 0x80);
510 }
511 }
512
513 return 0;
e246c333
LPC
514}
515
516static int adv7180_s_power(struct v4l2_subdev *sd, int on)
517{
518 struct adv7180_state *state = to_state(sd);
e246c333
LPC
519 int ret;
520
521 ret = mutex_lock_interruptible(&state->mutex);
522 if (ret)
523 return ret;
524
3999e5d0 525 ret = adv7180_set_power(state, on);
e246c333
LPC
526 if (ret == 0)
527 state->powered = on;
528
529 mutex_unlock(&state->mutex);
530 return ret;
531}
532
c9fbeddd 533static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
bca7ad1a 534{
c9fbeddd 535 struct v4l2_subdev *sd = to_adv7180_sd(ctrl);
bca7ad1a 536 struct adv7180_state *state = to_state(sd);
bca7ad1a 537 int ret = mutex_lock_interruptible(&state->mutex);
c9fbeddd
FV
538 int val;
539
bca7ad1a
FV
540 if (ret)
541 return ret;
c9fbeddd 542 val = ctrl->val;
bca7ad1a
FV
543 switch (ctrl->id) {
544 case V4L2_CID_BRIGHTNESS:
3999e5d0 545 ret = adv7180_write(state, ADV7180_REG_BRI, val);
bca7ad1a
FV
546 break;
547 case V4L2_CID_HUE:
bca7ad1a 548 /*Hue is inverted according to HSL chart */
3999e5d0 549 ret = adv7180_write(state, ADV7180_REG_HUE, -val);
bca7ad1a
FV
550 break;
551 case V4L2_CID_CONTRAST:
3999e5d0 552 ret = adv7180_write(state, ADV7180_REG_CON, val);
bca7ad1a
FV
553 break;
554 case V4L2_CID_SATURATION:
bca7ad1a
FV
555 /*
556 *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE
557 *Let's not confuse the user, everybody understands saturation
558 */
3999e5d0 559 ret = adv7180_write(state, ADV7180_REG_SD_SAT_CB, val);
bca7ad1a
FV
560 if (ret < 0)
561 break;
3999e5d0 562 ret = adv7180_write(state, ADV7180_REG_SD_SAT_CR, val);
bca7ad1a 563 break;
08b717c2
LPC
564 case V4L2_CID_ADV_FAST_SWITCH:
565 if (ctrl->val) {
566 /* ADI required write */
567 adv7180_write(state, 0x80d9, 0x44);
568 adv7180_write(state, ADV7180_REG_FLCONTROL,
569 ADV7180_FLCONTROL_FL_ENABLE);
570 } else {
571 /* ADI required write */
572 adv7180_write(state, 0x80d9, 0xc4);
573 adv7180_write(state, ADV7180_REG_FLCONTROL, 0x00);
574 }
575 break;
bca7ad1a
FV
576 default:
577 ret = -EINVAL;
578 }
579
580 mutex_unlock(&state->mutex);
581 return ret;
582}
583
c9fbeddd
FV
584static const struct v4l2_ctrl_ops adv7180_ctrl_ops = {
585 .s_ctrl = adv7180_s_ctrl,
586};
587
08b717c2
LPC
588static const struct v4l2_ctrl_config adv7180_ctrl_fast_switch = {
589 .ops = &adv7180_ctrl_ops,
590 .id = V4L2_CID_ADV_FAST_SWITCH,
591 .name = "Fast Switching",
592 .type = V4L2_CTRL_TYPE_BOOLEAN,
593 .min = 0,
594 .max = 1,
595 .step = 1,
596};
597
c9fbeddd
FV
598static int adv7180_init_controls(struct adv7180_state *state)
599{
600 v4l2_ctrl_handler_init(&state->ctrl_hdl, 4);
601
602 v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
603 V4L2_CID_BRIGHTNESS, ADV7180_BRI_MIN,
604 ADV7180_BRI_MAX, 1, ADV7180_BRI_DEF);
605 v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
606 V4L2_CID_CONTRAST, ADV7180_CON_MIN,
607 ADV7180_CON_MAX, 1, ADV7180_CON_DEF);
608 v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
609 V4L2_CID_SATURATION, ADV7180_SAT_MIN,
610 ADV7180_SAT_MAX, 1, ADV7180_SAT_DEF);
611 v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
612 V4L2_CID_HUE, ADV7180_HUE_MIN,
613 ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF);
08b717c2
LPC
614 v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL);
615
c9fbeddd
FV
616 state->sd.ctrl_handler = &state->ctrl_hdl;
617 if (state->ctrl_hdl.error) {
618 int err = state->ctrl_hdl.error;
619
620 v4l2_ctrl_handler_free(&state->ctrl_hdl);
621 return err;
622 }
623 v4l2_ctrl_handler_setup(&state->ctrl_hdl);
624
625 return 0;
626}
627static void adv7180_exit_controls(struct adv7180_state *state)
628{
629 v4l2_ctrl_handler_free(&state->ctrl_hdl);
630}
631
d5d51a82 632static int adv7180_enum_mbus_code(struct v4l2_subdev *sd,
f7234138 633 struct v4l2_subdev_pad_config *cfg,
d5d51a82 634 struct v4l2_subdev_mbus_code_enum *code)
cccb83f7 635{
d5d51a82 636 if (code->index != 0)
cccb83f7
VB
637 return -EINVAL;
638
6de690dd 639 code->code = MEDIA_BUS_FMT_UYVY8_2X8;
cccb83f7
VB
640
641 return 0;
642}
643
644static int adv7180_mbus_fmt(struct v4l2_subdev *sd,
645 struct v4l2_mbus_framefmt *fmt)
646{
647 struct adv7180_state *state = to_state(sd);
648
6de690dd 649 fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
cccb83f7 650 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
cccb83f7
VB
651 fmt->width = 720;
652 fmt->height = state->curr_norm & V4L2_STD_525_60 ? 480 : 576;
653
6457b626
NS
654 if (state->field == V4L2_FIELD_ALTERNATE)
655 fmt->height /= 2;
656
cccb83f7
VB
657 return 0;
658}
659
851a54ef
LPC
660static int adv7180_set_field_mode(struct adv7180_state *state)
661{
662 if (!(state->chip_info->flags & ADV7180_FLAG_I2P))
663 return 0;
664
665 if (state->field == V4L2_FIELD_NONE) {
666 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
667 adv7180_csi_write(state, 0x01, 0x20);
668 adv7180_csi_write(state, 0x02, 0x28);
669 adv7180_csi_write(state, 0x03, 0x38);
670 adv7180_csi_write(state, 0x04, 0x30);
671 adv7180_csi_write(state, 0x05, 0x30);
672 adv7180_csi_write(state, 0x06, 0x80);
673 adv7180_csi_write(state, 0x07, 0x70);
674 adv7180_csi_write(state, 0x08, 0x50);
675 }
676 adv7180_vpp_write(state, 0xa3, 0x00);
677 adv7180_vpp_write(state, 0x5b, 0x00);
678 adv7180_vpp_write(state, 0x55, 0x80);
679 } else {
680 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
681 adv7180_csi_write(state, 0x01, 0x18);
682 adv7180_csi_write(state, 0x02, 0x18);
683 adv7180_csi_write(state, 0x03, 0x30);
684 adv7180_csi_write(state, 0x04, 0x20);
685 adv7180_csi_write(state, 0x05, 0x28);
686 adv7180_csi_write(state, 0x06, 0x40);
687 adv7180_csi_write(state, 0x07, 0x58);
688 adv7180_csi_write(state, 0x08, 0x30);
689 }
690 adv7180_vpp_write(state, 0xa3, 0x70);
691 adv7180_vpp_write(state, 0x5b, 0x80);
692 adv7180_vpp_write(state, 0x55, 0x00);
693 }
694
695 return 0;
696}
697
d5d51a82 698static int adv7180_get_pad_format(struct v4l2_subdev *sd,
f7234138 699 struct v4l2_subdev_pad_config *cfg,
d5d51a82
LPC
700 struct v4l2_subdev_format *format)
701{
851a54ef
LPC
702 struct adv7180_state *state = to_state(sd);
703
704 if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
f7234138 705 format->format = *v4l2_subdev_get_try_format(sd, cfg, 0);
851a54ef
LPC
706 } else {
707 adv7180_mbus_fmt(sd, &format->format);
708 format->format.field = state->field;
709 }
710
711 return 0;
d5d51a82
LPC
712}
713
714static int adv7180_set_pad_format(struct v4l2_subdev *sd,
f7234138 715 struct v4l2_subdev_pad_config *cfg,
d5d51a82
LPC
716 struct v4l2_subdev_format *format)
717{
851a54ef
LPC
718 struct adv7180_state *state = to_state(sd);
719 struct v4l2_mbus_framefmt *framefmt;
e0ad7a9b 720 int ret;
851a54ef
LPC
721
722 switch (format->format.field) {
723 case V4L2_FIELD_NONE:
6457b626
NS
724 if (state->chip_info->flags & ADV7180_FLAG_I2P)
725 break;
726 /* fall through */
851a54ef 727 default:
6457b626 728 format->format.field = V4L2_FIELD_ALTERNATE;
851a54ef
LPC
729 break;
730 }
731
e0ad7a9b
NS
732 ret = adv7180_mbus_fmt(sd, &format->format);
733
851a54ef 734 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
851a54ef
LPC
735 if (state->field != format->format.field) {
736 state->field = format->format.field;
737 adv7180_set_power(state, false);
738 adv7180_set_field_mode(state);
739 adv7180_set_power(state, true);
740 }
741 } else {
f7234138 742 framefmt = v4l2_subdev_get_try_format(sd, cfg, 0);
851a54ef
LPC
743 *framefmt = format->format;
744 }
745
e0ad7a9b 746 return ret;
d5d51a82
LPC
747}
748
cccb83f7
VB
749static int adv7180_g_mbus_config(struct v4l2_subdev *sd,
750 struct v4l2_mbus_config *cfg)
751{
b37135e3
LPC
752 struct adv7180_state *state = to_state(sd);
753
754 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
2d95e7ed 755 cfg->type = V4L2_MBUS_CSI2_DPHY;
b37135e3
LPC
756 cfg->flags = V4L2_MBUS_CSI2_1_LANE |
757 V4L2_MBUS_CSI2_CHANNEL_0 |
758 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
759 } else {
760 /*
761 * The ADV7180 sensor supports BT.601/656 output modes.
762 * The BT.656 is default and not yet configurable by s/w.
763 */
764 cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
765 V4L2_MBUS_DATA_ACTIVE_HIGH;
766 cfg->type = V4L2_MBUS_BT656;
767 }
cccb83f7
VB
768
769 return 0;
770}
771
ecf37493 772static int adv7180_g_pixelaspect(struct v4l2_subdev *sd, struct v4l2_fract *aspect)
64b3df92
NS
773{
774 struct adv7180_state *state = to_state(sd);
775
776 if (state->curr_norm & V4L2_STD_525_60) {
ecf37493
HV
777 aspect->numerator = 11;
778 aspect->denominator = 10;
64b3df92 779 } else {
ecf37493
HV
780 aspect->numerator = 54;
781 aspect->denominator = 59;
64b3df92
NS
782 }
783
784 return 0;
785}
786
bae4c757
NS
787static int adv7180_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm)
788{
789 *norm = V4L2_STD_ALL;
790 return 0;
791}
792
937feeed
HV
793static int adv7180_s_stream(struct v4l2_subdev *sd, int enable)
794{
795 struct adv7180_state *state = to_state(sd);
796 int ret;
797
798 /* It's always safe to stop streaming, no need to take the lock */
799 if (!enable) {
800 state->streaming = enable;
801 return 0;
802 }
803
804 /* Must wait until querystd released the lock */
805 ret = mutex_lock_interruptible(&state->mutex);
806 if (ret)
807 return ret;
808 state->streaming = enable;
809 mutex_unlock(&state->mutex);
810 return 0;
811}
812
813static int adv7180_subscribe_event(struct v4l2_subdev *sd,
814 struct v4l2_fh *fh,
815 struct v4l2_event_subscription *sub)
816{
817 switch (sub->type) {
818 case V4L2_EVENT_SOURCE_CHANGE:
819 return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
820 case V4L2_EVENT_CTRL:
821 return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
822 default:
823 return -EINVAL;
824 }
825}
826
6789cb52 827static const struct v4l2_subdev_video_ops adv7180_video_ops = {
8774bed9 828 .s_std = adv7180_s_std,
d0fadc86 829 .g_std = adv7180_g_std,
38566d28 830 .g_frame_interval = adv7180_g_frame_interval,
6789cb52 831 .querystd = adv7180_querystd,
d3124294 832 .g_input_status = adv7180_g_input_status,
bca7ad1a 833 .s_routing = adv7180_s_routing,
cccb83f7 834 .g_mbus_config = adv7180_g_mbus_config,
ecf37493 835 .g_pixelaspect = adv7180_g_pixelaspect,
bae4c757 836 .g_tvnorms = adv7180_g_tvnorms,
937feeed 837 .s_stream = adv7180_s_stream,
6789cb52
RR
838};
839
840static const struct v4l2_subdev_core_ops adv7180_core_ops = {
e246c333 841 .s_power = adv7180_s_power,
937feeed
HV
842 .subscribe_event = adv7180_subscribe_event,
843 .unsubscribe_event = v4l2_event_subdev_unsubscribe,
6789cb52
RR
844};
845
d5d51a82
LPC
846static const struct v4l2_subdev_pad_ops adv7180_pad_ops = {
847 .enum_mbus_code = adv7180_enum_mbus_code,
848 .set_fmt = adv7180_set_pad_format,
849 .get_fmt = adv7180_get_pad_format,
850};
851
6789cb52
RR
852static const struct v4l2_subdev_ops adv7180_ops = {
853 .core = &adv7180_core_ops,
854 .video = &adv7180_video_ops,
d5d51a82 855 .pad = &adv7180_pad_ops,
6789cb52
RR
856};
857
0c25534d 858static irqreturn_t adv7180_irq(int irq, void *devid)
42752f7a 859{
0c25534d 860 struct adv7180_state *state = devid;
42752f7a
RR
861 u8 isr3;
862
863 mutex_lock(&state->mutex);
3999e5d0 864 isr3 = adv7180_read(state, ADV7180_REG_ISR3);
42752f7a 865 /* clear */
3999e5d0 866 adv7180_write(state, ADV7180_REG_ICR3, isr3);
42752f7a 867
937feeed
HV
868 if (isr3 & ADV7180_IRQ3_AD_CHANGE) {
869 static const struct v4l2_event src_ch = {
870 .type = V4L2_EVENT_SOURCE_CHANGE,
871 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
872 };
873
874 v4l2_subdev_notify_event(&state->sd, &src_ch);
875 }
42752f7a
RR
876 mutex_unlock(&state->mutex);
877
42752f7a
RR
878 return IRQ_HANDLED;
879}
880
f5dde49b 881static int adv7180_init(struct adv7180_state *state)
6789cb52 882{
6789cb52
RR
883 int ret;
884
42752f7a 885 /* ITU-R BT.656-4 compatible */
3999e5d0 886 ret = adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
bca7ad1a 887 ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
42752f7a 888 if (ret < 0)
f5dde49b 889 return ret;
bca7ad1a
FV
890
891 /* Manually set V bit end position in NTSC mode */
f5dde49b 892 return adv7180_write(state, ADV7180_REG_NTSC_V_BIT_END,
bca7ad1a 893 ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
f5dde49b
LPC
894}
895
896static int adv7180_set_std(struct adv7180_state *state, unsigned int std)
897{
898 return adv7180_write(state, ADV7180_REG_INPUT_CONTROL,
899 (std << 4) | state->input);
900}
901
902static int adv7180_select_input(struct adv7180_state *state, unsigned int input)
903{
904 int ret;
905
906 ret = adv7180_read(state, ADV7180_REG_INPUT_CONTROL);
bca7ad1a 907 if (ret < 0)
f5dde49b
LPC
908 return ret;
909
910 ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK;
911 ret |= input;
912 return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret);
913}
914
c5ef8f8c
LPC
915static int adv7182_init(struct adv7180_state *state)
916{
b37135e3
LPC
917 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
918 adv7180_write(state, ADV7180_REG_CSI_SLAVE_ADDR,
919 ADV7180_DEFAULT_CSI_I2C_ADDR << 1);
920
851a54ef
LPC
921 if (state->chip_info->flags & ADV7180_FLAG_I2P)
922 adv7180_write(state, ADV7180_REG_VPP_SLAVE_ADDR,
923 ADV7180_DEFAULT_VPP_I2C_ADDR << 1);
924
bf7dcb80
LPC
925 if (state->chip_info->flags & ADV7180_FLAG_V2) {
926 /* ADI recommended writes for improved video quality */
927 adv7180_write(state, 0x0080, 0x51);
928 adv7180_write(state, 0x0081, 0x51);
929 adv7180_write(state, 0x0082, 0x68);
bf7dcb80
LPC
930 }
931
c5ef8f8c 932 /* ADI required writes */
b37135e3 933 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
ce5d6290
SL
934 adv7180_write(state, ADV7180_REG_OUTPUT_CONTROL, 0x4e);
935 adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x57);
936 adv7180_write(state, ADV7180_REG_CTRL_2, 0xc0);
b37135e3
LPC
937 } else {
938 if (state->chip_info->flags & ADV7180_FLAG_V2)
ce5d6290
SL
939 adv7180_write(state,
940 ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
941 0x17);
b37135e3 942 else
ce5d6290
SL
943 adv7180_write(state,
944 ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
945 0x07);
946 adv7180_write(state, ADV7180_REG_OUTPUT_CONTROL, 0x0c);
947 adv7180_write(state, ADV7180_REG_CTRL_2, 0x40);
b37135e3
LPC
948 }
949
c5ef8f8c 950 adv7180_write(state, 0x0013, 0x00);
c5ef8f8c
LPC
951
952 return 0;
953}
954
955static int adv7182_set_std(struct adv7180_state *state, unsigned int std)
956{
957 return adv7180_write(state, ADV7182_REG_INPUT_VIDSEL, std << 4);
958}
959
960enum adv7182_input_type {
961 ADV7182_INPUT_TYPE_CVBS,
962 ADV7182_INPUT_TYPE_DIFF_CVBS,
963 ADV7182_INPUT_TYPE_SVIDEO,
964 ADV7182_INPUT_TYPE_YPBPR,
965};
966
967static enum adv7182_input_type adv7182_get_input_type(unsigned int input)
968{
969 switch (input) {
970 case ADV7182_INPUT_CVBS_AIN1:
971 case ADV7182_INPUT_CVBS_AIN2:
972 case ADV7182_INPUT_CVBS_AIN3:
973 case ADV7182_INPUT_CVBS_AIN4:
974 case ADV7182_INPUT_CVBS_AIN5:
975 case ADV7182_INPUT_CVBS_AIN6:
976 case ADV7182_INPUT_CVBS_AIN7:
977 case ADV7182_INPUT_CVBS_AIN8:
978 return ADV7182_INPUT_TYPE_CVBS;
979 case ADV7182_INPUT_SVIDEO_AIN1_AIN2:
980 case ADV7182_INPUT_SVIDEO_AIN3_AIN4:
981 case ADV7182_INPUT_SVIDEO_AIN5_AIN6:
982 case ADV7182_INPUT_SVIDEO_AIN7_AIN8:
983 return ADV7182_INPUT_TYPE_SVIDEO;
984 case ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3:
985 case ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6:
986 return ADV7182_INPUT_TYPE_YPBPR;
987 case ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2:
988 case ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4:
989 case ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6:
990 case ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8:
991 return ADV7182_INPUT_TYPE_DIFF_CVBS;
992 default: /* Will never happen */
993 return 0;
994 }
995}
996
997/* ADI recommended writes to registers 0x52, 0x53, 0x54 */
998static unsigned int adv7182_lbias_settings[][3] = {
999 [ADV7182_INPUT_TYPE_CVBS] = { 0xCB, 0x4E, 0x80 },
1000 [ADV7182_INPUT_TYPE_DIFF_CVBS] = { 0xC0, 0x4E, 0x80 },
1001 [ADV7182_INPUT_TYPE_SVIDEO] = { 0x0B, 0xCE, 0x80 },
1002 [ADV7182_INPUT_TYPE_YPBPR] = { 0x0B, 0x4E, 0xC0 },
1003};
1004
bf7dcb80
LPC
1005static unsigned int adv7280_lbias_settings[][3] = {
1006 [ADV7182_INPUT_TYPE_CVBS] = { 0xCD, 0x4E, 0x80 },
1007 [ADV7182_INPUT_TYPE_DIFF_CVBS] = { 0xC0, 0x4E, 0x80 },
1008 [ADV7182_INPUT_TYPE_SVIDEO] = { 0x0B, 0xCE, 0x80 },
1009 [ADV7182_INPUT_TYPE_YPBPR] = { 0x0B, 0x4E, 0xC0 },
1010};
1011
c5ef8f8c
LPC
1012static int adv7182_select_input(struct adv7180_state *state, unsigned int input)
1013{
1014 enum adv7182_input_type input_type;
1015 unsigned int *lbias;
1016 unsigned int i;
1017 int ret;
1018
1019 ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, input);
1020 if (ret)
1021 return ret;
1022
1023 /* Reset clamp circuitry - ADI recommended writes */
ce5d6290
SL
1024 adv7180_write(state, ADV7180_REG_RST_CLAMP, 0x00);
1025 adv7180_write(state, ADV7180_REG_RST_CLAMP, 0xff);
c5ef8f8c
LPC
1026
1027 input_type = adv7182_get_input_type(input);
1028
1029 switch (input_type) {
1030 case ADV7182_INPUT_TYPE_CVBS:
1031 case ADV7182_INPUT_TYPE_DIFF_CVBS:
1032 /* ADI recommends to use the SH1 filter */
ce5d6290 1033 adv7180_write(state, ADV7180_REG_SHAP_FILTER_CTL_1, 0x41);
c5ef8f8c
LPC
1034 break;
1035 default:
ce5d6290 1036 adv7180_write(state, ADV7180_REG_SHAP_FILTER_CTL_1, 0x01);
c5ef8f8c
LPC
1037 break;
1038 }
1039
bf7dcb80
LPC
1040 if (state->chip_info->flags & ADV7180_FLAG_V2)
1041 lbias = adv7280_lbias_settings[input_type];
1042 else
1043 lbias = adv7182_lbias_settings[input_type];
c5ef8f8c
LPC
1044
1045 for (i = 0; i < ARRAY_SIZE(adv7182_lbias_settings[0]); i++)
ce5d6290 1046 adv7180_write(state, ADV7180_REG_CVBS_TRIM + i, lbias[i]);
c5ef8f8c
LPC
1047
1048 if (input_type == ADV7182_INPUT_TYPE_DIFF_CVBS) {
1049 /* ADI required writes to make differential CVBS work */
ce5d6290
SL
1050 adv7180_write(state, ADV7180_REG_RES_CIR, 0xa8);
1051 adv7180_write(state, ADV7180_REG_CLAMP_ADJ, 0x90);
1052 adv7180_write(state, ADV7180_REG_DIFF_MODE, 0xb0);
1053 adv7180_write(state, ADV7180_REG_AGC_ADJ1, 0x08);
1054 adv7180_write(state, ADV7180_REG_AGC_ADJ2, 0xa0);
c5ef8f8c 1055 } else {
ce5d6290
SL
1056 adv7180_write(state, ADV7180_REG_RES_CIR, 0xf0);
1057 adv7180_write(state, ADV7180_REG_CLAMP_ADJ, 0xd0);
1058 adv7180_write(state, ADV7180_REG_DIFF_MODE, 0x10);
1059 adv7180_write(state, ADV7180_REG_AGC_ADJ1, 0x9c);
1060 adv7180_write(state, ADV7180_REG_AGC_ADJ2, 0x00);
c5ef8f8c
LPC
1061 }
1062
1063 return 0;
1064}
1065
f5dde49b
LPC
1066static const struct adv7180_chip_info adv7180_info = {
1067 .flags = ADV7180_FLAG_RESET_POWERED,
1068 /* We cannot discriminate between LQFP and 40-pin LFCSP, so accept
1069 * all inputs and let the card driver take care of validation
1070 */
1071 .valid_input_mask = BIT(ADV7180_INPUT_CVBS_AIN1) |
1072 BIT(ADV7180_INPUT_CVBS_AIN2) |
1073 BIT(ADV7180_INPUT_CVBS_AIN3) |
1074 BIT(ADV7180_INPUT_CVBS_AIN4) |
1075 BIT(ADV7180_INPUT_CVBS_AIN5) |
1076 BIT(ADV7180_INPUT_CVBS_AIN6) |
1077 BIT(ADV7180_INPUT_SVIDEO_AIN1_AIN2) |
1078 BIT(ADV7180_INPUT_SVIDEO_AIN3_AIN4) |
1079 BIT(ADV7180_INPUT_SVIDEO_AIN5_AIN6) |
1080 BIT(ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3) |
1081 BIT(ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6),
1082 .init = adv7180_init,
1083 .set_std = adv7180_set_std,
1084 .select_input = adv7180_select_input,
1085};
1086
c5ef8f8c
LPC
1087static const struct adv7180_chip_info adv7182_info = {
1088 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
1089 BIT(ADV7182_INPUT_CVBS_AIN2) |
1090 BIT(ADV7182_INPUT_CVBS_AIN3) |
1091 BIT(ADV7182_INPUT_CVBS_AIN4) |
1092 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
1093 BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
1094 BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
1095 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
1096 BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4),
1097 .init = adv7182_init,
1098 .set_std = adv7182_set_std,
1099 .select_input = adv7182_select_input,
1100};
1101
bf7dcb80 1102static const struct adv7180_chip_info adv7280_info = {
851a54ef 1103 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P,
bf7dcb80
LPC
1104 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
1105 BIT(ADV7182_INPUT_CVBS_AIN2) |
1106 BIT(ADV7182_INPUT_CVBS_AIN3) |
1107 BIT(ADV7182_INPUT_CVBS_AIN4) |
1108 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
1109 BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
1110 BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3),
1111 .init = adv7182_init,
1112 .set_std = adv7182_set_std,
1113 .select_input = adv7182_select_input,
1114};
1115
b37135e3 1116static const struct adv7180_chip_info adv7280_m_info = {
851a54ef 1117 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P,
b37135e3
LPC
1118 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
1119 BIT(ADV7182_INPUT_CVBS_AIN2) |
1120 BIT(ADV7182_INPUT_CVBS_AIN3) |
1121 BIT(ADV7182_INPUT_CVBS_AIN4) |
1122 BIT(ADV7182_INPUT_CVBS_AIN5) |
1123 BIT(ADV7182_INPUT_CVBS_AIN6) |
1124 BIT(ADV7182_INPUT_CVBS_AIN7) |
1125 BIT(ADV7182_INPUT_CVBS_AIN8) |
1126 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
1127 BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
1128 BIT(ADV7182_INPUT_SVIDEO_AIN5_AIN6) |
1129 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
1130 BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
1131 BIT(ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6),
1132 .init = adv7182_init,
1133 .set_std = adv7182_set_std,
1134 .select_input = adv7182_select_input,
1135};
1136
bf7dcb80 1137static const struct adv7180_chip_info adv7281_info = {
b37135e3
LPC
1138 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
1139 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
1140 BIT(ADV7182_INPUT_CVBS_AIN2) |
1141 BIT(ADV7182_INPUT_CVBS_AIN7) |
1142 BIT(ADV7182_INPUT_CVBS_AIN8) |
1143 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
1144 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
1145 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
1146 BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
1147 .init = adv7182_init,
1148 .set_std = adv7182_set_std,
1149 .select_input = adv7182_select_input,
1150};
1151
1152static const struct adv7180_chip_info adv7281_m_info = {
1153 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
1154 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
1155 BIT(ADV7182_INPUT_CVBS_AIN2) |
1156 BIT(ADV7182_INPUT_CVBS_AIN3) |
1157 BIT(ADV7182_INPUT_CVBS_AIN4) |
1158 BIT(ADV7182_INPUT_CVBS_AIN7) |
1159 BIT(ADV7182_INPUT_CVBS_AIN8) |
1160 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
1161 BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
1162 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
1163 BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
1164 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
1165 BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
1166 BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
1167 .init = adv7182_init,
1168 .set_std = adv7182_set_std,
1169 .select_input = adv7182_select_input,
1170};
1171
1172static const struct adv7180_chip_info adv7281_ma_info = {
1173 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
bf7dcb80
LPC
1174 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
1175 BIT(ADV7182_INPUT_CVBS_AIN2) |
b37135e3
LPC
1176 BIT(ADV7182_INPUT_CVBS_AIN3) |
1177 BIT(ADV7182_INPUT_CVBS_AIN4) |
1178 BIT(ADV7182_INPUT_CVBS_AIN5) |
1179 BIT(ADV7182_INPUT_CVBS_AIN6) |
bf7dcb80
LPC
1180 BIT(ADV7182_INPUT_CVBS_AIN7) |
1181 BIT(ADV7182_INPUT_CVBS_AIN8) |
1182 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
b37135e3
LPC
1183 BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
1184 BIT(ADV7182_INPUT_SVIDEO_AIN5_AIN6) |
bf7dcb80 1185 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
b37135e3
LPC
1186 BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
1187 BIT(ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6) |
bf7dcb80 1188 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
b37135e3
LPC
1189 BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
1190 BIT(ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6) |
bf7dcb80
LPC
1191 BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
1192 .init = adv7182_init,
1193 .set_std = adv7182_set_std,
1194 .select_input = adv7182_select_input,
1195};
1196
851a54ef
LPC
1197static const struct adv7180_chip_info adv7282_info = {
1198 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P,
1199 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
1200 BIT(ADV7182_INPUT_CVBS_AIN2) |
1201 BIT(ADV7182_INPUT_CVBS_AIN7) |
1202 BIT(ADV7182_INPUT_CVBS_AIN8) |
1203 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
1204 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
1205 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
1206 BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
1207 .init = adv7182_init,
1208 .set_std = adv7182_set_std,
1209 .select_input = adv7182_select_input,
1210};
1211
1212static const struct adv7180_chip_info adv7282_m_info = {
1213 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P,
1214 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
1215 BIT(ADV7182_INPUT_CVBS_AIN2) |
1216 BIT(ADV7182_INPUT_CVBS_AIN3) |
1217 BIT(ADV7182_INPUT_CVBS_AIN4) |
1218 BIT(ADV7182_INPUT_CVBS_AIN7) |
1219 BIT(ADV7182_INPUT_CVBS_AIN8) |
1220 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
1221 BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
1222 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
1223 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
1224 BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
1225 BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
1226 .init = adv7182_init,
1227 .set_std = adv7182_set_std,
1228 .select_input = adv7182_select_input,
1229};
1230
f5dde49b
LPC
1231static int init_device(struct adv7180_state *state)
1232{
1233 int ret;
1234
1235 mutex_lock(&state->mutex);
1236
65d9e14a
SL
1237 adv7180_set_power_pin(state, true);
1238
f5dde49b 1239 adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES);
16dfe72f 1240 usleep_range(5000, 10000);
f5dde49b
LPC
1241
1242 ret = state->chip_info->init(state);
1243 if (ret)
3999e5d0 1244 goto out_unlock;
42752f7a 1245
f5dde49b
LPC
1246 ret = adv7180_program_std(state);
1247 if (ret)
1248 goto out_unlock;
42752f7a 1249
851a54ef
LPC
1250 adv7180_set_field_mode(state);
1251
42752f7a
RR
1252 /* register for interrupts */
1253 if (state->irq > 0) {
42752f7a 1254 /* config the Interrupt pin to be active low */
3999e5d0 1255 ret = adv7180_write(state, ADV7180_REG_ICONF1,
bca7ad1a
FV
1256 ADV7180_ICONF1_ACTIVE_LOW |
1257 ADV7180_ICONF1_PSYNC_ONLY);
42752f7a 1258 if (ret < 0)
3999e5d0 1259 goto out_unlock;
42752f7a 1260
3999e5d0 1261 ret = adv7180_write(state, ADV7180_REG_IMR1, 0);
42752f7a 1262 if (ret < 0)
3999e5d0 1263 goto out_unlock;
42752f7a 1264
3999e5d0 1265 ret = adv7180_write(state, ADV7180_REG_IMR2, 0);
42752f7a 1266 if (ret < 0)
3999e5d0 1267 goto out_unlock;
42752f7a
RR
1268
1269 /* enable AD change interrupts interrupts */
3999e5d0 1270 ret = adv7180_write(state, ADV7180_REG_IMR3,
bca7ad1a 1271 ADV7180_IRQ3_AD_CHANGE);
42752f7a 1272 if (ret < 0)
3999e5d0 1273 goto out_unlock;
42752f7a 1274
3999e5d0 1275 ret = adv7180_write(state, ADV7180_REG_IMR4, 0);
42752f7a 1276 if (ret < 0)
3999e5d0 1277 goto out_unlock;
6789cb52
RR
1278 }
1279
3999e5d0
LPC
1280out_unlock:
1281 mutex_unlock(&state->mutex);
df065b37 1282
df065b37 1283 return ret;
bca7ad1a
FV
1284}
1285
4c62e976
GKH
1286static int adv7180_probe(struct i2c_client *client,
1287 const struct i2c_device_id *id)
bca7ad1a
FV
1288{
1289 struct adv7180_state *state;
1290 struct v4l2_subdev *sd;
1291 int ret;
1292
1293 /* Check if the adapter supports the needed features */
1294 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1295 return -EIO;
1296
1297 v4l_info(client, "chip found @ 0x%02x (%s)\n",
1298 client->addr, client->adapter->name);
1299
c02b211d 1300 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
7657e064
FE
1301 if (state == NULL)
1302 return -ENOMEM;
bca7ad1a 1303
3999e5d0 1304 state->client = client;
6457b626 1305 state->field = V4L2_FIELD_ALTERNATE;
f5dde49b 1306 state->chip_info = (struct adv7180_chip_info *)id->driver_data;
3999e5d0 1307
65d9e14a
SL
1308 state->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
1309 GPIOD_OUT_HIGH);
1310 if (IS_ERR(state->pwdn_gpio)) {
1311 ret = PTR_ERR(state->pwdn_gpio);
1312 v4l_err(client, "request for power pin failed: %d\n", ret);
1313 return ret;
1314 }
1315
b37135e3
LPC
1316 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
1317 state->csi_client = i2c_new_dummy(client->adapter,
1318 ADV7180_DEFAULT_CSI_I2C_ADDR);
1319 if (!state->csi_client)
1320 return -ENOMEM;
1321 }
1322
851a54ef
LPC
1323 if (state->chip_info->flags & ADV7180_FLAG_I2P) {
1324 state->vpp_client = i2c_new_dummy(client->adapter,
1325 ADV7180_DEFAULT_VPP_I2C_ADDR);
1326 if (!state->vpp_client) {
1327 ret = -ENOMEM;
1328 goto err_unregister_csi_client;
1329 }
1330 }
1331
bca7ad1a 1332 state->irq = client->irq;
bca7ad1a 1333 mutex_init(&state->mutex);
937feeed 1334 state->curr_norm = V4L2_STD_NTSC;
f5dde49b
LPC
1335 if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED)
1336 state->powered = true;
1337 else
1338 state->powered = false;
bca7ad1a
FV
1339 state->input = 0;
1340 sd = &state->sd;
1341 v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
5cc72c47 1342 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
bca7ad1a 1343
c9fbeddd
FV
1344 ret = adv7180_init_controls(state);
1345 if (ret)
851a54ef 1346 goto err_unregister_vpp_client;
d5d51a82
LPC
1347
1348 state->pad.flags = MEDIA_PAD_FL_SOURCE;
ca0fa5f0 1349 sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
ab22e77c 1350 ret = media_entity_pads_init(&sd->entity, 1, &state->pad);
c9fbeddd
FV
1351 if (ret)
1352 goto err_free_ctrl;
fa5b7945 1353
d5d51a82
LPC
1354 ret = init_device(state);
1355 if (ret)
1356 goto err_media_entity_cleanup;
1357
fa5721d1
LPC
1358 if (state->irq) {
1359 ret = request_threaded_irq(client->irq, NULL, adv7180_irq,
f3e991d4
LPC
1360 IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
1361 KBUILD_MODNAME, state);
fa5721d1 1362 if (ret)
d5d51a82 1363 goto err_media_entity_cleanup;
fa5721d1
LPC
1364 }
1365
fa5b7945
LPC
1366 ret = v4l2_async_register_subdev(sd);
1367 if (ret)
1368 goto err_free_irq;
1369
6789cb52 1370 return 0;
42752f7a 1371
fa5b7945
LPC
1372err_free_irq:
1373 if (state->irq > 0)
1374 free_irq(client->irq, state);
d5d51a82
LPC
1375err_media_entity_cleanup:
1376 media_entity_cleanup(&sd->entity);
c9fbeddd
FV
1377err_free_ctrl:
1378 adv7180_exit_controls(state);
851a54ef 1379err_unregister_vpp_client:
297aca18 1380 i2c_unregister_device(state->vpp_client);
b37135e3 1381err_unregister_csi_client:
297aca18 1382 i2c_unregister_device(state->csi_client);
297a0ae3 1383 mutex_destroy(&state->mutex);
42752f7a 1384 return ret;
6789cb52
RR
1385}
1386
4c62e976 1387static int adv7180_remove(struct i2c_client *client)
6789cb52
RR
1388{
1389 struct v4l2_subdev *sd = i2c_get_clientdata(client);
42752f7a
RR
1390 struct adv7180_state *state = to_state(sd);
1391
fa5b7945
LPC
1392 v4l2_async_unregister_subdev(sd);
1393
0c25534d 1394 if (state->irq > 0)
42752f7a 1395 free_irq(client->irq, state);
6789cb52 1396
d5d51a82 1397 media_entity_cleanup(&sd->entity);
b13f4af2 1398 adv7180_exit_controls(state);
b37135e3 1399
297aca18
AS
1400 i2c_unregister_device(state->vpp_client);
1401 i2c_unregister_device(state->csi_client);
b37135e3 1402
65d9e14a
SL
1403 adv7180_set_power_pin(state, false);
1404
297a0ae3 1405 mutex_destroy(&state->mutex);
b37135e3 1406
6789cb52
RR
1407 return 0;
1408}
1409
1410static const struct i2c_device_id adv7180_id[] = {
f5dde49b 1411 { "adv7180", (kernel_ulong_t)&adv7180_info },
281ddc3c
UH
1412 { "adv7180cp", (kernel_ulong_t)&adv7180_info },
1413 { "adv7180st", (kernel_ulong_t)&adv7180_info },
c5ef8f8c 1414 { "adv7182", (kernel_ulong_t)&adv7182_info },
bf7dcb80 1415 { "adv7280", (kernel_ulong_t)&adv7280_info },
b37135e3 1416 { "adv7280-m", (kernel_ulong_t)&adv7280_m_info },
bf7dcb80 1417 { "adv7281", (kernel_ulong_t)&adv7281_info },
b37135e3
LPC
1418 { "adv7281-m", (kernel_ulong_t)&adv7281_m_info },
1419 { "adv7281-ma", (kernel_ulong_t)&adv7281_ma_info },
851a54ef
LPC
1420 { "adv7282", (kernel_ulong_t)&adv7282_info },
1421 { "adv7282-m", (kernel_ulong_t)&adv7282_m_info },
6789cb52
RR
1422 {},
1423};
f5dde49b 1424MODULE_DEVICE_TABLE(i2c, adv7180_id);
6789cb52 1425
cc1088dc
LPC
1426#ifdef CONFIG_PM_SLEEP
1427static int adv7180_suspend(struct device *dev)
bca7ad1a 1428{
cc1088dc 1429 struct i2c_client *client = to_i2c_client(dev);
e246c333
LPC
1430 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1431 struct adv7180_state *state = to_state(sd);
bca7ad1a 1432
3999e5d0 1433 return adv7180_set_power(state, false);
bca7ad1a
FV
1434}
1435
cc1088dc 1436static int adv7180_resume(struct device *dev)
bca7ad1a 1437{
cc1088dc 1438 struct i2c_client *client = to_i2c_client(dev);
bca7ad1a
FV
1439 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1440 struct adv7180_state *state = to_state(sd);
1441 int ret;
1442
3999e5d0 1443 ret = init_device(state);
bca7ad1a
FV
1444 if (ret < 0)
1445 return ret;
c18818e9
LPC
1446
1447 ret = adv7180_set_power(state, state->powered);
1448 if (ret)
1449 return ret;
1450
bca7ad1a
FV
1451 return 0;
1452}
cc1088dc
LPC
1453
1454static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume);
1455#define ADV7180_PM_OPS (&adv7180_pm_ops)
1456
1457#else
1458#define ADV7180_PM_OPS NULL
bca7ad1a
FV
1459#endif
1460
250121d3
BD
1461#ifdef CONFIG_OF
1462static const struct of_device_id adv7180_of_id[] = {
1463 { .compatible = "adi,adv7180", },
ce1ec5c0
UH
1464 { .compatible = "adi,adv7180cp", },
1465 { .compatible = "adi,adv7180st", },
bf14e74c
JS
1466 { .compatible = "adi,adv7182", },
1467 { .compatible = "adi,adv7280", },
1468 { .compatible = "adi,adv7280-m", },
1469 { .compatible = "adi,adv7281", },
1470 { .compatible = "adi,adv7281-m", },
1471 { .compatible = "adi,adv7281-ma", },
1472 { .compatible = "adi,adv7282", },
1473 { .compatible = "adi,adv7282-m", },
250121d3
BD
1474 { },
1475};
1476
1477MODULE_DEVICE_TABLE(of, adv7180_of_id);
1478#endif
1479
6789cb52
RR
1480static struct i2c_driver adv7180_driver = {
1481 .driver = {
c9fbeddd 1482 .name = KBUILD_MODNAME,
cc1088dc 1483 .pm = ADV7180_PM_OPS,
250121d3 1484 .of_match_table = of_match_ptr(adv7180_of_id),
bca7ad1a
FV
1485 },
1486 .probe = adv7180_probe,
4c62e976 1487 .remove = adv7180_remove,
bca7ad1a 1488 .id_table = adv7180_id,
6789cb52
RR
1489};
1490
c6e8d86f 1491module_i2c_driver(adv7180_driver);
6789cb52
RR
1492
1493MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver");
1494MODULE_AUTHOR("Mocean Laboratories");
1495MODULE_LICENSE("GPL v2");