⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adv7180.c

📁 ADV7180 linux驱动源代码。基于三星S3C6410的ADV7180 linux驱动程序。ARM。
💻 C
字号:
  1 /*
  2  * ADV7180 Analog decoder driver for S3C2443X
  3  * 
  4  * Jaecheol Lee <jc.lee@samsung.com>
  5  * 2007.08.08   
  6  */
  7 
  8 #include <linux/module.h>
  9 #include <linux/kernel.h>
 10 #include <linux/init.h>
 11 #include <linux/i2c.h>
 12 #include <linux/i2c-id.h>
 13 #include <linux/slab.h>
 14 #include <linux/string.h>
 15 #include <linux/init.h>
 16 #include <linux/delay.h>
 17 #include <linux/video_decoder.h>
 18 #include <media/v4l2-dev.h>
 19 
 20 //#include <asm/arch/registers.h>
 21 #include "../s3c_camif.h"
 22 #include "adv7180.h"
 23 
 24 
 25 
 26 static const char *sensor_version =
 27     "adv7180.c, v 1.00 2007/08/08 jc.lee@samsung.com";
 28 
 29 
 30 static struct i2c_driver i2c_driver_adv7180;
 31 
 32 /* This is an abstract CIS sensor for MSDMA input. */
 33 
 34 camif_cis_t msdma_input = {
 35         itu_fmt:       CAMIF_ITU601,
 36         order422:      CAMIF_YCBYCR,            /* YCRYCB */
 37         camclk:        32000000,                /* No effect */
 38         source_x:      800,       
 39         source_y:      480,
 40         win_hor_ofst:  0,
 41         win_ver_ofst:  0,
 42         win_hor_ofst2: 0,
 43         win_ver_ofst2: 0,
 44         polarity_pclk: 0,
 45         polarity_vsync:1,
 46         polarity_href: 0,
 47         reset_type:CAMIF_EX_RESET_AH, /* Ref board has inverted signal */
 48         reset_udelay: 20000,
 49 };
 50 
 51 camif_cis_t interlace_input = {
 52         itu_fmt:       CAMIF_ITU656,
 53         order422:      CAMIF_CBYCRY,            /* YCRYCB */
 54         camclk:        32000000,                /* No effect */
 55         source_x:      720,       
 56         source_y:      243,
 57         win_hor_ofst:  0,
 58         win_ver_ofst:  0,
 59         win_hor_ofst2: 0,
 60         win_ver_ofst2: 0,
 61         polarity_pclk: 0,
 62         polarity_vsync:0,
 63         polarity_href: 0,
 64         reset_type:CAMIF_EX_RESET_AH, /* Ref board has inverted signal */
 65         reset_udelay: 20000,
 66 };
 67 
 68 
 69 extern camif_cis_t* get_initialized_cis();
 70 camif_cis_t* get_initialized_cis() {
 71         if(interlace_input.init_sensor == 0) return NULL;
 72         return &interlace_input;
 73 
 74 }
 75 
 76 static unsigned short ignore[] = { I2C_CLIENT_END };
 77 static unsigned short normal_addr[] = { (I2C_ADV7180 >> 1), I2C_CLIENT_END };
 78 static unsigned short *forces[] = { NULL };
 79 
 80 static struct i2c_client_address_data addr_data = {
 81       normal_i2c:normal_addr,
 82       //normal_i2c_range:ignore,
 83       probe:ignore,
 84       //probe_range:ignore,
 85       ignore:ignore,
 86       //ignore_range:ignore,
 87       forces:forces,
 88 };
 89 
 90 
 91 static inline int
 92 adv7180_write (struct i2c_client *client,
 93                u8                 reg,
 94                u8                 value)
 95 {
 96         struct adv7180 *decoder = i2c_get_clientdata(client);
 97         decoder->reg[reg] = value;
 98         return i2c_smbus_write_byte_data(client, reg, value);
 99 }
100 
101 static inline int
102 adv7180_read (struct i2c_client *client,
103               u8                 reg)
104 {
105         return i2c_smbus_read_byte_data(client, reg);
106 }
107 
108 static int
109 adv7180_write_block (struct i2c_client *client,
110                      const u8          *data,
111                      unsigned int       len)
112 {
113         int ret = -1;
114         u8 reg;
115 
116         /* the adv7180 has an autoincrement function, use it if
117          * the adapter understands raw I2C */
118         if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
119                 /* do raw I2C, not smbus compatible */
120                 struct adv7180 *decoder = i2c_get_clientdata(client);
121                 struct i2c_msg msg;
122                 u8 block_data[32];
123 
124                 msg.addr = client->addr;
125                 msg.flags = 0;
126                 while (len >= 2) {
127                         msg.buf = (char *) block_data;
128                         msg.len = 0;
129                         block_data[msg.len++] = reg = data[0];
130                         do {
131                                 block_data[msg.len++] =
132                                     decoder->reg[reg++] = data[1];
133                                 len -= 2;
134                                 data += 2;
135                         } while (len >= 2 && data[0] == reg &&
136                                  msg.len < 32);
137                         if ((ret = i2c_transfer(client->adapter,
138                                                 &msg, 1)) < 0)
139                                 break;
140                 }
141         } else {
142                 /* do some slow I2C emulation kind of thing */
143                 while (len >= 2) {
144                         reg = *data++;
145                         if ((ret = adv7180_write(client, reg,
146                                                  *data++)) < 0)
147                                 break;
148                         len -= 2;
149                 }
150         }
151 
152         return ret;
153 }
154 
155 
156 static int
157 adv7180_detect_client (struct i2c_adapter *adapter,
158                        int                 address,
159                        int                 kind)
160 {
161         int i;
162         struct i2c_client *client;
163         struct adv7180 *decoder;
164         char *dname;
165 
166         /* Check if the adapter supports the needed features */
167         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_EMUL))
168                 return 0;
169 
170         client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
171         if (client == 0)
172                 return -ENOMEM;
173         client->addr = address;
174         client->adapter = adapter;
175         client->driver = &i2c_driver_adv7180;
176         if ((client->addr == I2C_ADV7180 >> 1) ||
177             (client->addr == (I2C_ADV7180 >> 1) + 1)) {
178                 dname = adv7180_name;
179         } else {
180                 /* We should never get here!!! */
181                 kfree(client);
182                 return 0;
183         }
184 
185         client->data = &interlace_input;
186         interlace_input.sensor = client;
187         camif_register_cis(client);
188         
189         strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
190 
191         decoder = kzalloc(sizeof(struct adv7180), GFP_KERNEL);
192         if (decoder == NULL) {
193                 kfree(client);
194                 return -ENOMEM;
195         }
196         decoder->norm = VIDEO_MODE_NTSC;
197         decoder->input = 0;
198         decoder->enable = 1;
199         i2c_set_clientdata(client, decoder);
200 
201         i = i2c_attach_client(client);
202         if (i) {
203                 kfree(client);
204                 kfree(decoder);
205                 return i;
206         }
207 
208         i = adv7180_write_block(client, init_composite, sizeof(init_composite));
209         if (i >= 0) {
210 
211         }
212         if (i < 0) {
213         }
214 
215         return 0;
216 }
217 
218 
219 
220 static int adv7180_attach_adapter(struct i2c_adapter *adap)
221 {
222         return i2c_probe(adap, &addr_data, adv7180_detect_client);
223 }
224 
225 static int adv7180_detach_client(struct i2c_client *client)
226 {
227         int err;
228         err = i2c_detach_client(client);
229         if(err) {
230                 return err;
231         }
232         camif_unregister_cis(client);
233 
234         kfree(client);
235         return 0;
236 }
237 
238 static int
239 adv7180_command (struct i2c_client *client,
240                  unsigned int       cmd,
241                  void              *arg)
242 {
243         int tmp;
244         u64 endtime;
245         
246         struct adv7180 *decoder = i2c_get_clientdata(client);
247 
248         switch (cmd) {
249 
250         case 0:
251                 /* This is just for testing!!! */
252                 adv7180_write_block(client, init_composite,
253                                     sizeof(init_composite));
254                 break;
255                 
256         case USER_ADD:
257                 adv7180_write(client, 0x0f, (1<<7)); // Reset
258                 endtime = get_jiffies_64() + RESET_DELAY;
259                 while(jiffies < endtime); // Delay for a 5 ms
260                 break;
261                 
262         case USER_EXIT:
263                 adv7180_write(client, 0x0f, (1<<5)); // PWRDWN : 1
264                 break;
265 
266         case DECODER_INIT:
267                 break;          
268 
269         case DECODER_GET_STATUS:
270         {
271                 int *iarg = arg;
272 
273                 tmp = adv7180_read(client, 0x10) & 0x000000ff; // STATUS1
274                 tmp = (tmp | (adv7180_read(client, 0x11) & 0x000000ff)<<8); //  + IDENTIFICATION
275                 tmp = (tmp | (adv7180_read(client, 0x12) & 0x000000ff)<<16); // + STATUS2
276                 tmp = (tmp | (adv7180_read(client, 0x13) & 0x000000ff)<<24); // + STATUS3
277 
278                 *iarg = tmp;
279         }
280                 break;
281 
282         case DECODER_GET_CAPABILITIES:
283         {
284                 struct video_decoder_capability *cap = arg;
285 
286                 cap->flags = VIDEO_DECODER_NTSC |
287                              VIDEO_DECODER_PAL; /* well, hacky */
288                 cap->inputs = 2;
289                 cap->outputs = 1;
290         }
291                 break;
292 
293         case DECODER_SET_NORM:
294         {
295                 int iarg = *(int *) arg;
296                 switch (iarg) {
297 
298                 case 0: // Composite
299                         adv7180_write_block(client, init_composite,
300                                             sizeof(init_composite));
301                         break;
302 
303                 case 1: //S-VIDEO
304                         adv7180_write_block(client, init_svideo,
305                                             sizeof(init_svideo));
306                         break;
307 
308                 case 2: // Component
309                         adv7180_write_block(client, init_component,
310                             sizeof(init_component));
311                         break;
312                 default:
313                         return -EINVAL;
314 
315                 }
316 
317                 decoder->norm = iarg;
318         }
319                 break;
320 
321         case DECODER_SET_INPUT:
322         {
323                 int iarg = *(int *) arg;
324                 decoder->input = iarg;
325 
326                 switch(decoder->input) {
327 
328                 case CVBS:
329                         adv7180_write_block(client, init_composite,
330                                             sizeof(init_composite));
331                         break;
332                         
333                 case SVIDEO:
334                         adv7180_write_block(client, init_svideo,
335                                             sizeof(init_svideo));
336                         break;
337                         
338                 case YPbPr:
339                         adv7180_write_block(client, init_component,
340                             sizeof(init_component));
341                         break;
342                         
343                 default:
344                         return -EINVAL;
345 
346                 }
347         }
348                 break;
349 
350         case DECODER_SET_OUTPUT:
351         {
352                 int *iarg = arg;
353 
354                 if (*iarg != 0) {
355                         return -EINVAL;
356                 }
357         }
358                 break;
359 
360         case DECODER_ENABLE_OUTPUT:
361         {
362                 int *iarg = arg;
363 
364                 decoder->enable = !!*iarg;
365         }
366                 break;
367 
368         case DECODER_SET_GPIO:
369         {
370                 int *iarg = arg;
371                 switch(*iarg) {
372                 case 0: // Pin 37 output is Field signal
373                         adv7180_write(client, 0x58, 0x00);
374                         break;
375                         
376                 case 1: // Output is Vsync signal
377                         adv7180_write(client, 0x58, (1<<0));
378                         break;
379                         
380                 default:
381                         return -EINVAL;
382                 }
383         }
384                 break;
385                 
386         default:
387                 return -EINVAL;
388         }
389 
390         return 0;
391 }
392 
393 static struct i2c_driver i2c_driver_adv7180 = {
394         .driver = {
395                 .name = "adv7180",
396         },
397       .id = I2C_DRIVERID_ADV7170, /* Must be fixed!!! */
398 
399       .attach_adapter = adv7180_attach_adapter,
400       .detach_client = adv7180_detach_client,
401       .command = adv7180_command
402 };
403 
404 static __init int adv7180_init(void)
405 {
406         return i2c_add_driver(&i2c_driver_adv7180);
407 }
408 
409 
410 static __init void adv7180_exit(void)
411 {
412         i2c_del_driver(&i2c_driver_adv7180);
413 }
414 
415 module_init(adv7180_init)
416 module_exit(adv7180_exit)
417 
418 MODULE_AUTHOR("JaeCheol Lee <jc.lee@samsung.com>");
419 MODULE_DESCRIPTION("I2C Client Driver For ADV7180 video decoder");
420 MODULE_LICENSE("GPL");
421 
422 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -