77eada64cf746e9d727d6842e811d73b33d8ec4d
[safe/jmp/linux-2.6] / drivers / media / video / adv7180.c
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
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
51 #define ADV7180_AUTODETECT_ENABLE_REG   0x07
52 #define ADV7180_AUTODETECT_DEFAULT      0x7f
53
54
55 #define ADV7180_STATUS1_REG                             0x10
56 #define ADV7180_STATUS1_IN_LOCK         0x01
57 #define ADV7180_STATUS1_AUTOD_MASK      0x70
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
71 struct adv7180_state {
72         struct v4l2_subdev      sd;
73         v4l2_std_id             curr_norm;
74         bool                    autodetect;
75 };
76
77 static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
78 {
79         switch (status1 & ADV7180_STATUS1_AUTOD_MASK) {
80         case ADV7180_STATUS1_AUTOD_NTSM_M_J:
81                 return V4L2_STD_NTSC;
82         case ADV7180_STATUS1_AUTOD_NTSC_4_43:
83                 return V4L2_STD_NTSC_443;
84         case ADV7180_STATUS1_AUTOD_PAL_M:
85                 return V4L2_STD_PAL_M;
86         case ADV7180_STATUS1_AUTOD_PAL_60:
87                 return V4L2_STD_PAL_60;
88         case ADV7180_STATUS1_AUTOD_PAL_B_G:
89                 return V4L2_STD_PAL;
90         case ADV7180_STATUS1_AUTOD_SECAM:
91                 return V4L2_STD_SECAM;
92         case ADV7180_STATUS1_AUTOD_PAL_COMB:
93                 return V4L2_STD_PAL_Nc | V4L2_STD_PAL_N;
94         case ADV7180_STATUS1_AUTOD_SECAM_525:
95                 return V4L2_STD_SECAM;
96         default:
97                 return V4L2_STD_UNKNOWN;
98         }
99 }
100
101 static int v4l2_std_to_adv7180(v4l2_std_id std)
102 {
103         if (std == V4L2_STD_PAL_60)
104                 return ADV7180_INPUT_CONTROL_PAL60;
105         if (std == V4L2_STD_NTSC_443)
106                 return ADV7180_INPUT_CONTROL_NTSC_443;
107         if (std == V4L2_STD_PAL_N)
108                 return ADV7180_INPUT_CONTROL_PAL_N;
109         if (std == V4L2_STD_PAL_M)
110                 return ADV7180_INPUT_CONTROL_PAL_M;
111         if (std == V4L2_STD_PAL_Nc)
112                 return ADV7180_INPUT_CONTROL_PAL_COMB_N;
113
114         if (std & V4L2_STD_PAL)
115                 return ADV7180_INPUT_CONTROL_PAL_BG;
116         if (std & V4L2_STD_NTSC)
117                 return ADV7180_INPUT_CONTROL_NTSC_M;
118         if (std & V4L2_STD_SECAM)
119                 return ADV7180_INPUT_CONTROL_PAL_SECAM;
120
121         return -EINVAL;
122 }
123
124 static u32 adv7180_status_to_v4l2(u8 status1)
125 {
126         if (!(status1 & ADV7180_STATUS1_IN_LOCK))
127                 return V4L2_IN_ST_NO_SIGNAL;
128
129         return 0;
130 }
131
132 static int __adv7180_status(struct i2c_client *client, u32 *status,
133         v4l2_std_id *std)
134 {
135         int status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG);
136
137         if (status1 < 0)
138                 return status1;
139
140         if (status)
141                 *status = adv7180_status_to_v4l2(status1);
142         if (std)
143                 *std = adv7180_std_to_v4l2(status1);
144
145         return 0;
146 }
147
148 static inline struct adv7180_state *to_state(struct v4l2_subdev *sd)
149 {
150         return container_of(sd, struct adv7180_state, sd);
151 }
152
153 static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
154 {
155         struct adv7180_state *state = to_state(sd);
156         int err = 0;
157
158         if (!state->autodetect)
159                 *std = state->curr_norm;
160         else
161                 err = __adv7180_status(v4l2_get_subdevdata(sd), NULL, std);
162
163         return err;
164 }
165
166 static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status)
167 {
168         return __adv7180_status(v4l2_get_subdevdata(sd), status, NULL);
169 }
170
171 static int adv7180_g_chip_ident(struct v4l2_subdev *sd,
172         struct v4l2_dbg_chip_ident *chip)
173 {
174         struct i2c_client *client = v4l2_get_subdevdata(sd);
175
176         return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7180, 0);
177 }
178
179 static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
180 {
181         struct adv7180_state *state = to_state(sd);
182         struct i2c_client *client = v4l2_get_subdevdata(sd);
183         int ret;
184
185         /* all standards -> autodetect */
186         if (std == V4L2_STD_ALL) {
187                 ret = i2c_smbus_write_byte_data(client,
188                         ADV7180_INPUT_CONTROL_REG,
189                         ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM);
190                 if (ret < 0)
191                         goto out;
192
193                 state->autodetect = true;
194         } else {
195                 ret = v4l2_std_to_adv7180(std);
196                 if (ret < 0)
197                         goto out;
198
199                 ret = i2c_smbus_write_byte_data(client,
200                         ADV7180_INPUT_CONTROL_REG, ret);
201                 if (ret < 0)
202                         goto out;
203
204                 state->curr_norm = std;
205                 state->autodetect = false;
206         }
207         ret = 0;
208 out:
209         return ret;
210 }
211
212 static const struct v4l2_subdev_video_ops adv7180_video_ops = {
213         .querystd = adv7180_querystd,
214         .g_input_status = adv7180_g_input_status,
215 };
216
217 static const struct v4l2_subdev_core_ops adv7180_core_ops = {
218         .g_chip_ident = adv7180_g_chip_ident,
219         .s_std = adv7180_s_std,
220 };
221
222 static const struct v4l2_subdev_ops adv7180_ops = {
223         .core = &adv7180_core_ops,
224         .video = &adv7180_video_ops,
225 };
226
227 /*
228  * Generic i2c probe
229  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
230  */
231
232 static __devinit int adv7180_probe(struct i2c_client *client,
233                         const struct i2c_device_id *id)
234 {
235         struct adv7180_state *state;
236         struct v4l2_subdev *sd;
237         int ret;
238
239         /* Check if the adapter supports the needed features */
240         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
241                 return -EIO;
242
243         v4l_info(client, "chip found @ 0x%02x (%s)\n",
244                         client->addr << 1, client->adapter->name);
245
246         state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL);
247         if (state == NULL)
248                 return -ENOMEM;
249         state->autodetect = true;
250         sd = &state->sd;
251         v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
252
253         /* Initialize adv7180 */
254         /* enable autodetection */
255         ret = i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG,
256                 ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM);
257         if (ret > 0)
258                 ret = i2c_smbus_write_byte_data(client,
259                         ADV7180_AUTODETECT_ENABLE_REG,
260                         ADV7180_AUTODETECT_DEFAULT);
261         if (ret < 0) {
262                 printk(KERN_ERR DRIVER_NAME
263                         ": Failed to communicate to chip: %d\n", ret);
264                 return ret;
265         }
266
267         return 0;
268 }
269
270 static __devexit int adv7180_remove(struct i2c_client *client)
271 {
272         struct v4l2_subdev *sd = i2c_get_clientdata(client);
273
274         v4l2_device_unregister_subdev(sd);
275         kfree(to_state(sd));
276         return 0;
277 }
278
279 static const struct i2c_device_id adv7180_id[] = {
280         {DRIVER_NAME, 0},
281         {},
282 };
283
284 MODULE_DEVICE_TABLE(i2c, adv7180_id);
285
286 static struct i2c_driver adv7180_driver = {
287         .driver = {
288                 .owner  = THIS_MODULE,
289                 .name   = DRIVER_NAME,
290         },
291         .probe          = adv7180_probe,
292         .remove         = __devexit_p(adv7180_remove),
293         .id_table       = adv7180_id,
294 };
295
296 static __init int adv7180_init(void)
297 {
298         return i2c_add_driver(&adv7180_driver);
299 }
300
301 static __exit void adv7180_exit(void)
302 {
303         i2c_del_driver(&adv7180_driver);
304 }
305
306 module_init(adv7180_init);
307 module_exit(adv7180_exit);
308
309 MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver");
310 MODULE_AUTHOR("Mocean Laboratories");
311 MODULE_LICENSE("GPL v2");
312