]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/staging/tm6000/tm6000-core.c
V4L/DVB (12808): tm6000: Move analog tv standards to tm6000-stds
[karo-tx-linux.git] / drivers / staging / tm6000 / tm6000-core.c
1 /*
2    tm6000-core.c - driver for TM5600/TM6000 USB video capture devices
3
4    Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
5
6    Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
7        - DVB-T support
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation version 2
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/usb.h>
26 #include <linux/i2c.h>
27 #include <linux/video_decoder.h>
28 #include "tm6000.h"
29 #include "tm6000-regs.h"
30 #include <media/v4l2-common.h>
31 #include <media/tuner.h>
32
33 #ifdef HACK /* HACK */
34 #include "tm6000-hack.c"
35 #endif
36
37 #define USB_TIMEOUT     5*HZ /* ms */
38
39 int tm6000_read_write_usb (struct tm6000_core *dev, u8 req_type, u8 req,
40                            u16 value, u16 index, u8 *buf, u16 len)
41 {
42         int          ret, i;
43         unsigned int pipe;
44         static int   ini=0, last=0, n=0;
45         u8           *data=NULL;
46
47         if (len)
48                 data = kzalloc(len, GFP_KERNEL);
49
50
51         if (req_type & USB_DIR_IN)
52                 pipe=usb_rcvctrlpipe(dev->udev, 0);
53         else {
54                 pipe=usb_sndctrlpipe(dev->udev, 0);
55                 memcpy(data, buf, len);
56         }
57
58         if (tm6000_debug & V4L2_DEBUG_I2C) {
59                 if (!ini)
60                         last=ini=jiffies;
61
62                 printk("%06i (dev %p, pipe %08x): ", n, dev->udev, pipe);
63
64                 printk( "%s: %06u ms %06u ms %02x %02x %02x %02x %02x %02x %02x %02x ",
65                         (req_type & USB_DIR_IN)?" IN":"OUT",
66                         jiffies_to_msecs(jiffies-last),
67                         jiffies_to_msecs(jiffies-ini),
68                         req_type, req,value&0xff,value>>8, index&0xff, index>>8,
69                         len&0xff, len>>8);
70                 last=jiffies;
71                 n++;
72
73                 if ( !(req_type & USB_DIR_IN) ) {
74                         printk(">>> ");
75                         for (i=0;i<len;i++) {
76                                 printk(" %02x",buf[i]);
77                         }
78                         printk("\n");
79                 }
80         }
81
82         ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index, data,
83                               len, USB_TIMEOUT);
84
85         if (req_type &  USB_DIR_IN)
86                 memcpy(buf, data, len);
87
88         if (tm6000_debug & V4L2_DEBUG_I2C) {
89                 if (ret<0) {
90                         if (req_type &  USB_DIR_IN)
91                                 printk("<<< (len=%d)\n",len);
92
93                         printk("%s: Error #%d\n", __FUNCTION__, ret);
94                 } else if (req_type &  USB_DIR_IN) {
95                         printk("<<< ");
96                         for (i=0;i<len;i++) {
97                                 printk(" %02x",buf[i]);
98                         }
99                         printk("\n");
100                 }
101         }
102
103         kfree(data);
104
105         msleep(5);
106
107         return ret;
108 }
109
110 int tm6000_set_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index)
111 {
112         return
113                 tm6000_read_write_usb (dev, USB_DIR_OUT | USB_TYPE_VENDOR,
114                                        req, value, index, NULL, 0);
115 }
116
117 int tm6000_get_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index)
118 {
119         int rc;
120         u8 buf[1];
121
122         rc=tm6000_read_write_usb (dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
123                                        value, index, buf, 1);
124
125         if (rc<0)
126                 return rc;
127
128         return *buf;
129 }
130
131 int tm6000_get_reg16 (struct tm6000_core *dev, u8 req, u16 value, u16 index)
132 {
133         int rc;
134         u8 buf[2];
135
136         rc=tm6000_read_write_usb (dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
137                                        value, index, buf, 2);
138
139         if (rc<0)
140                 return rc;
141
142         return buf[1]|buf[0]<<8;
143 }
144
145 void tm6000_set_fourcc_format(struct tm6000_core *dev)
146 {
147         if (dev->fourcc==V4L2_PIX_FMT_UYVY) {
148                 /* Sets driver to UYUV */
149                 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xc1, 0xd0);
150         } else {
151                 /* Sets driver to YUV2 */
152                 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xc1, 0x90);
153         }
154 }
155
156 int tm6000_init_analog_mode (struct tm6000_core *dev)
157 {
158
159         /* Enables soft reset */
160         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x3f, 0x01);
161
162         if (dev->scaler) {
163                 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xc0, 0x20);
164         } else {
165                 /* Enable Hfilter and disable TS Drop err */
166                 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xc0, 0x80);
167         }
168         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xc3, 0x88);
169         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xda, 0x23);
170         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xd1, 0xc0);
171         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xd2, 0xd8);
172         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xd6, 0x06);
173         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xdf, 0x1f);
174
175         /* AP Software reset */
176         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xff, 0x08);
177         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xff, 0x00);
178
179         tm6000_set_fourcc_format(dev);
180
181         /* Disables soft reset */
182         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x3f, 0x00);
183
184         /* E3: Select input 0 - TV tuner */
185         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xe3, 0x00);
186         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xeb, 0x60);
187
188         /* Tuner firmware can now be loaded */
189
190         tm6000_set_reg (dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_1, 0x00);
191         msleep(11);
192
193         /* This controls input */
194         tm6000_set_reg (dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_2, 0x0);
195         tm6000_set_reg (dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_3, 0x01);
196         msleep(20);
197
198         /*FIXME: Hack!!! */
199         struct v4l2_frequency f;
200         mutex_lock(&dev->lock);
201         f.frequency=dev->freq;
202         tm6000_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f);
203         mutex_unlock(&dev->lock);
204
205         msleep(100);
206         tm6000_set_standard (dev, &dev->norm);
207         tm6000_set_audio_bitrate (dev,48000);
208
209
210         return 0;
211 }
212
213 int tm6000_init_digital_mode (struct tm6000_core *dev)
214 {
215         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00ff, 0x08);
216         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00ff, 0x00);
217         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x003f, 0x01);
218         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00df, 0x08);
219         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00e2, 0x0c);
220         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00e8, 0xff);
221         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00eb, 0xd8);
222         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00c0, 0x40);
223         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00c1, 0xd0);
224         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00c3, 0x09);
225         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00da, 0x37);
226         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00d1, 0xd8);
227         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00d2, 0xc0);
228         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00d6, 0x60);
229
230         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00e2, 0x0c);
231         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00e8, 0xff);
232         tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00eb, 0x08);
233         msleep(50);
234
235         tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
236         msleep(50);
237         tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01);
238         msleep(50);
239         tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
240         msleep(100);
241
242         return 0;
243 }
244
245 /* The meaning of those initializations are unknown */
246 u8 init_tab[][2] = {
247         /* REG  VALUE */
248         { 0xdf, 0x1f },
249         { 0xff, 0x08 },
250         { 0xff, 0x00 },
251         { 0xd5, 0x4f },
252         { 0xda, 0x23 },
253         { 0xdb, 0x08 },
254         { 0xe2, 0x00 },
255         { 0xe3, 0x10 },
256         { 0xe5, 0x00 },
257         { 0xe8, 0x00 },
258         { 0xeb, 0x64 },         /* 48000 bits/sample, external input */
259         { 0xee, 0xc2 },
260         { 0x3f, 0x01 },         /* Start of soft reset */
261         { 0x00, 0x00 },
262         { 0x01, 0x07 },
263         { 0x02, 0x5f },
264         { 0x03, 0x00 },
265         { 0x05, 0x64 },
266         { 0x07, 0x01 },
267         { 0x08, 0x82 },
268         { 0x09, 0x36 },
269         { 0x0a, 0x50 },
270         { 0x0c, 0x6a },
271         { 0x11, 0xc9 },
272         { 0x12, 0x07 },
273         { 0x13, 0x3b },
274         { 0x14, 0x47 },
275         { 0x15, 0x6f },
276         { 0x17, 0xcd },
277         { 0x18, 0x1e },
278         { 0x19, 0x8b },
279         { 0x1a, 0xa2 },
280         { 0x1b, 0xe9 },
281         { 0x1c, 0x1c },
282         { 0x1d, 0xcc },
283         { 0x1e, 0xcc },
284         { 0x1f, 0xcd },
285         { 0x20, 0x3c },
286         { 0x21, 0x3c },
287         { 0x2d, 0x48 },
288         { 0x2e, 0x88 },
289         { 0x30, 0x22 },
290         { 0x31, 0x61 },
291         { 0x32, 0x74 },
292         { 0x33, 0x1c },
293         { 0x34, 0x74 },
294         { 0x35, 0x1c },
295         { 0x36, 0x7a },
296         { 0x37, 0x26 },
297         { 0x38, 0x40 },
298         { 0x39, 0x0a },
299         { 0x42, 0x55 },
300         { 0x51, 0x11 },
301         { 0x55, 0x01 },
302         { 0x57, 0x02 },
303         { 0x58, 0x35 },
304         { 0x59, 0xa0 },
305         { 0x80, 0x15 },
306         { 0x82, 0x42 },
307         { 0xc1, 0xd0 },
308         { 0xc3, 0x88 },
309         { 0x3f, 0x00 },         /* End of the soft reset */
310 };
311
312 int tm6000_init (struct tm6000_core *dev)
313 {
314         int board, rc=0, i;
315
316 #ifdef HACK /* HACK */
317         init_tm6000(dev);
318         return 0;
319 #else
320
321         /* Load board's initialization table */
322         for (i=0; i< ARRAY_SIZE(init_tab); i++) {
323                 rc= tm6000_set_reg (dev, REQ_07_SET_GET_AVREG,
324                         init_tab[i][0],init_tab[i][1]);
325                 if (rc<0) {
326                         printk (KERN_ERR "Error %i while setting reg %d to value %d\n",
327                         rc, init_tab[i][0],init_tab[i][1]);
328                         return rc;
329                 }
330         }
331
332         /* Check board version - maybe 10Moons specific */
333         board=tm6000_get_reg16 (dev, 0x40, 0, 0);
334         if (board >=0) {
335                 printk (KERN_INFO "Board version = 0x%04x\n",board);
336         } else {
337                 printk (KERN_ERR "Error %i while retrieving board version\n",board);
338         }
339
340         tm6000_set_reg (dev, REQ_05_SET_GET_USBREG, 0x18, 0x00);
341         msleep(5); /* Just to be conservative */
342
343         /* Reset GPIO1 and GPIO4. */
344         for (i=0; i< 2; i++) {
345                 rc=tm6000_set_reg (dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_1, 0);
346                 if (rc<0) {
347                         printk (KERN_ERR "Error %i doing GPIO1 reset\n",rc);
348                         return rc;
349                 }
350
351                 msleep(10); /* Just to be conservative */
352                 rc=tm6000_set_reg (dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_1, 1);
353                 if (rc<0) {
354                         printk (KERN_ERR "Error %i doing GPIO1 reset\n",rc);
355                         return rc;
356                 }
357
358                 msleep(10);
359                 rc=tm6000_set_reg (dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_4, 0);
360                 if (rc<0) {
361                         printk (KERN_ERR "Error %i doing GPIO4 reset\n",rc);
362                         return rc;
363                 }
364
365                 msleep(10);
366                 rc=tm6000_set_reg (dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_4, 1);
367                 if (rc<0) {
368                         printk (KERN_ERR "Error %i doing GPIO4 reset\n",rc);
369                         return rc;
370                 }
371
372                 if (!i)
373                         rc=tm6000_get_reg16(dev, 0x40,0,0);
374         }
375
376         msleep(50);
377
378 #endif /* HACK */
379
380         return 0;
381 }
382
383 int tm6000_set_audio_bitrate (struct tm6000_core *dev, int bitrate)
384 {
385         int val;
386
387         val=tm6000_get_reg (dev, REQ_07_SET_GET_AVREG, 0xeb, 0x0);
388 printk("Original value=%d\n",val);
389         if (val<0)
390                 return val;
391
392         val &= 0x0f;            /* Preserve the audio input control bits */
393         switch (bitrate) {
394         case 44100:
395                 val|=0xd0;
396                 dev->audio_bitrate=bitrate;
397                 break;
398         case 48000:
399                 val|=0x60;
400                 dev->audio_bitrate=bitrate;
401                 break;
402         }
403         val=tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xeb, val);
404
405         return val;
406 }