V4L/DVB (13173): adv7180: Support for getting input status
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / media / video / adv7180.c
CommitLineData
6789cb52
RR
1/*
2 * adv7180.c Analog Devices ADV7180 video decoder driver
3 * Copyright (c) 2009 Intel Corporation
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/errno.h>
22#include <linux/kernel.h>
23#include <linux/interrupt.h>
24#include <linux/i2c.h>
25#include <linux/i2c-id.h>
26#include <media/v4l2-ioctl.h>
27#include <linux/videodev2.h>
28#include <media/v4l2-device.h>
29#include <media/v4l2-chip-ident.h>
30
31#define DRIVER_NAME "adv7180"
32
d3124294
RR
33#define ADV7180_INPUT_CONTROL_REG 0x00
34#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00
35#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10
36#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_J_SECAM 0x20
37#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_M_SECAM 0x30
38#define ADV7180_INPUT_CONTROL_NTSC_J 0x40
39#define ADV7180_INPUT_CONTROL_NTSC_M 0x50
40#define ADV7180_INPUT_CONTROL_PAL60 0x60
41#define ADV7180_INPUT_CONTROL_NTSC_443 0x70
42#define ADV7180_INPUT_CONTROL_PAL_BG 0x80
43#define ADV7180_INPUT_CONTROL_PAL_N 0x90
44#define ADV7180_INPUT_CONTROL_PAL_M 0xa0
45#define ADV7180_INPUT_CONTROL_PAL_M_PED 0xb0
46#define ADV7180_INPUT_CONTROL_PAL_COMB_N 0xc0
47#define ADV7180_INPUT_CONTROL_PAL_COMB_N_PED 0xd0
48#define ADV7180_INPUT_CONTROL_PAL_SECAM 0xe0
49#define ADV7180_INPUT_CONTROL_PAL_SECAM_PED 0xf0
50
6789cb52
RR
51#define ADV7180_AUTODETECT_ENABLE_REG 0x07
52#define ADV7180_AUTODETECT_DEFAULT 0x7f
53
54
d3124294
RR
55#define ADV7180_STATUS1_REG 0x10
56#define ADV7180_STATUS1_IN_LOCK 0x01
57#define ADV7180_STATUS1_AUTOD_MASK 0x70
6789cb52
RR
58#define ADV7180_STATUS1_AUTOD_NTSM_M_J 0x00
59#define ADV7180_STATUS1_AUTOD_NTSC_4_43 0x10
60#define ADV7180_STATUS1_AUTOD_PAL_M 0x20
61#define ADV7180_STATUS1_AUTOD_PAL_60 0x30
62#define ADV7180_STATUS1_AUTOD_PAL_B_G 0x40
63#define ADV7180_STATUS1_AUTOD_SECAM 0x50
64#define ADV7180_STATUS1_AUTOD_PAL_COMB 0x60
65#define ADV7180_STATUS1_AUTOD_SECAM_525 0x70
66
67#define ADV7180_IDENT_REG 0x11
68#define ADV7180_ID_7180 0x18
69
70
71struct adv7180_state {
72 struct v4l2_subdev sd;
73};
74
d3124294 75static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
6789cb52 76{
6789cb52
RR
77 switch (status1 & ADV7180_STATUS1_AUTOD_MASK) {
78 case ADV7180_STATUS1_AUTOD_NTSM_M_J:
d3124294 79 return V4L2_STD_NTSC;
6789cb52
RR
80 case ADV7180_STATUS1_AUTOD_NTSC_4_43:
81 return V4L2_STD_NTSC_443;
82 case ADV7180_STATUS1_AUTOD_PAL_M:
83 return V4L2_STD_PAL_M;
84 case ADV7180_STATUS1_AUTOD_PAL_60:
85 return V4L2_STD_PAL_60;
86 case ADV7180_STATUS1_AUTOD_PAL_B_G:
87 return V4L2_STD_PAL;
88 case ADV7180_STATUS1_AUTOD_SECAM:
89 return V4L2_STD_SECAM;
90 case ADV7180_STATUS1_AUTOD_PAL_COMB:
91 return V4L2_STD_PAL_Nc | V4L2_STD_PAL_N;
92 case ADV7180_STATUS1_AUTOD_SECAM_525:
93 return V4L2_STD_SECAM;
94 default:
95 return V4L2_STD_UNKNOWN;
96 }
97}
98
d3124294
RR
99static u32 adv7180_status_to_v4l2(u8 status1)
100{
101 if (!(status1 & ADV7180_STATUS1_IN_LOCK))
102 return V4L2_IN_ST_NO_SIGNAL;
103
104 return 0;
105}
106
107static int __adv7180_status(struct i2c_client *client, u32 *status,
108 v4l2_std_id *std)
109{
110 int status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG);
111
112 if (status1 < 0)
113 return status1;
114
115 if (status)
116 *status = adv7180_status_to_v4l2(status1);
117 if (std)
118 *std = adv7180_std_to_v4l2(status1);
119
120 return 0;
121}
122
6789cb52
RR
123static inline struct adv7180_state *to_state(struct v4l2_subdev *sd)
124{
125 return container_of(sd, struct adv7180_state, sd);
126}
127
128static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
129{
d3124294
RR
130 return __adv7180_status(v4l2_get_subdevdata(sd), NULL, std);
131}
6789cb52 132
d3124294
RR
133static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status)
134{
135 return __adv7180_status(v4l2_get_subdevdata(sd), status, NULL);
6789cb52
RR
136}
137
138static int adv7180_g_chip_ident(struct v4l2_subdev *sd,
139 struct v4l2_dbg_chip_ident *chip)
140{
141 struct i2c_client *client = v4l2_get_subdevdata(sd);
142
143 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7180, 0);
144}
145
146static const struct v4l2_subdev_video_ops adv7180_video_ops = {
147 .querystd = adv7180_querystd,
d3124294 148 .g_input_status = adv7180_g_input_status,
6789cb52
RR
149};
150
151static const struct v4l2_subdev_core_ops adv7180_core_ops = {
152 .g_chip_ident = adv7180_g_chip_ident,
153};
154
155static const struct v4l2_subdev_ops adv7180_ops = {
156 .core = &adv7180_core_ops,
157 .video = &adv7180_video_ops,
158};
159
160/*
161 * Generic i2c probe
162 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
163 */
164
165static int adv7180_probe(struct i2c_client *client,
166 const struct i2c_device_id *id)
167{
168 struct adv7180_state *state;
169 struct v4l2_subdev *sd;
170 int ret;
171
172 /* Check if the adapter supports the needed features */
173 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
174 return -EIO;
175
176 v4l_info(client, "chip found @ 0x%02x (%s)\n",
177 client->addr << 1, client->adapter->name);
178
179 state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL);
180 if (state == NULL)
181 return -ENOMEM;
182 sd = &state->sd;
183 v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
184
185 /* Initialize adv7180 */
186 /* enable autodetection */
187 ret = i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG,
d3124294 188 ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM);
6789cb52
RR
189 if (ret > 0)
190 ret = i2c_smbus_write_byte_data(client,
191 ADV7180_AUTODETECT_ENABLE_REG,
192 ADV7180_AUTODETECT_DEFAULT);
193 if (ret < 0) {
194 printk(KERN_ERR DRIVER_NAME
195 ": Failed to communicate to chip: %d\n", ret);
196 return ret;
197 }
198
199 return 0;
200}
201
202static int adv7180_remove(struct i2c_client *client)
203{
204 struct v4l2_subdev *sd = i2c_get_clientdata(client);
205
206 v4l2_device_unregister_subdev(sd);
207 kfree(to_state(sd));
208 return 0;
209}
210
211static const struct i2c_device_id adv7180_id[] = {
212 {DRIVER_NAME, 0},
213 {},
214};
215
216MODULE_DEVICE_TABLE(i2c, adv7180_id);
217
218static struct i2c_driver adv7180_driver = {
219 .driver = {
220 .owner = THIS_MODULE,
221 .name = DRIVER_NAME,
222 },
223 .probe = adv7180_probe,
224 .remove = adv7180_remove,
225 .id_table = adv7180_id,
226};
227
228static __init int adv7180_init(void)
229{
230 return i2c_add_driver(&adv7180_driver);
231}
232
233static __exit void adv7180_exit(void)
234{
235 i2c_del_driver(&adv7180_driver);
236}
237
238module_init(adv7180_init);
239module_exit(adv7180_exit);
240
241MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver");
242MODULE_AUTHOR("Mocean Laboratories");
243MODULE_LICENSE("GPL v2");
244