[media] tm6000: Don't try to use a non-existing interface
[pandora-kernel.git] / drivers / staging / tm6000 / tm6000-core.c
1 /*
2  *  tm6000-core.c - driver for TM5600/TM6000/TM6010 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/slab.h>
26 #include <linux/usb.h>
27 #include <linux/i2c.h>
28 #include "tm6000.h"
29 #include "tm6000-regs.h"
30 #include <media/v4l2-common.h>
31 #include <media/tuner.h>
32
33 #define USB_TIMEOUT     (5 * HZ) /* ms */
34
35 int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
36                           u16 value, u16 index, u8 *buf, u16 len)
37 {
38         int          ret, i;
39         unsigned int pipe;
40         u8           *data = NULL;
41
42         mutex_lock(&dev->usb_lock);
43
44         if (len)
45                 data = kzalloc(len, GFP_KERNEL);
46
47         if (req_type & USB_DIR_IN)
48                 pipe = usb_rcvctrlpipe(dev->udev, 0);
49         else {
50                 pipe = usb_sndctrlpipe(dev->udev, 0);
51                 memcpy(data, buf, len);
52         }
53
54         if (tm6000_debug & V4L2_DEBUG_I2C) {
55                 printk("(dev %p, pipe %08x): ", dev->udev, pipe);
56
57                 printk("%s: %02x %02x %02x %02x %02x %02x %02x %02x ",
58                         (req_type & USB_DIR_IN) ? " IN" : "OUT",
59                         req_type, req, value&0xff, value>>8, index&0xff,
60                         index>>8, len&0xff, len>>8);
61
62                 if (!(req_type & USB_DIR_IN)) {
63                         printk(">>> ");
64                         for (i = 0; i < len; i++)
65                                 printk(" %02x", buf[i]);
66                         printk("\n");
67                 }
68         }
69
70         ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index,
71                               data, len, USB_TIMEOUT);
72
73         if (req_type &  USB_DIR_IN)
74                 memcpy(buf, data, len);
75
76         if (tm6000_debug & V4L2_DEBUG_I2C) {
77                 if (ret < 0) {
78                         if (req_type &  USB_DIR_IN)
79                                 printk("<<< (len=%d)\n", len);
80
81                         printk("%s: Error #%d\n", __FUNCTION__, ret);
82                 } else if (req_type &  USB_DIR_IN) {
83                         printk("<<< ");
84                         for (i = 0; i < len; i++)
85                                 printk(" %02x", buf[i]);
86                         printk("\n");
87                 }
88         }
89
90         kfree(data);
91         msleep(5);
92
93         mutex_unlock(&dev->usb_lock);
94         return ret;
95 }
96
97 int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
98 {
99         return
100                 tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
101                                       req, value, index, NULL, 0);
102 }
103 EXPORT_SYMBOL_GPL(tm6000_set_reg);
104
105 int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
106 {
107         int rc;
108         u8 buf[1];
109
110         rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
111                                         value, index, buf, 1);
112
113         if (rc < 0)
114                 return rc;
115
116         return *buf;
117 }
118 EXPORT_SYMBOL_GPL(tm6000_get_reg);
119
120 int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
121                                                 u16 index, u16 mask)
122 {
123         int rc;
124         u8 buf[1];
125         u8 new_index;
126
127         rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
128                                         value, index, buf, 1);
129
130         if (rc < 0)
131                 return rc;
132
133         new_index = (buf[0] & ~mask) | (index & mask);
134
135         if (new_index == index)
136                 return 0;
137
138         return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
139                                       req, value, new_index, NULL, 0);
140 }
141 EXPORT_SYMBOL_GPL(tm6000_set_reg_mask);
142
143 int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index)
144 {
145         int rc;
146         u8 buf[2];
147
148         rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
149                                         value, index, buf, 2);
150
151         if (rc < 0)
152                 return rc;
153
154         return buf[1]|buf[0]<<8;
155 }
156
157 int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index)
158 {
159         int rc;
160         u8 buf[4];
161
162         rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
163                                         value, index, buf, 4);
164
165         if (rc < 0)
166                 return rc;
167
168         return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
169 }
170
171 int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep)
172 {
173         int rc;
174
175         rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
176         if (rc < 0)
177                 return rc;
178
179         msleep(tsleep);
180
181         rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
182         msleep(tsleep);
183
184         return rc;
185 }
186
187 void tm6000_set_fourcc_format(struct tm6000_core *dev)
188 {
189         if (dev->dev_type == TM6010) {
190                 int val;
191
192                 val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, 0) & 0xfc;
193                 if (dev->fourcc == V4L2_PIX_FMT_UYVY)
194                         tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val);
195                 else
196                         tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val | 1);
197         } else {
198                 if (dev->fourcc == V4L2_PIX_FMT_UYVY)
199                         tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
200                 else
201                         tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0x90);
202         }
203 }
204
205 static void tm6000_set_vbi(struct tm6000_core *dev)
206 {
207         /*
208          * FIXME:
209          * VBI lines and start/end are different between 60Hz and 50Hz
210          * So, it is very likely that we need to change the config to
211          * something that takes it into account, doing something different
212          * if (dev->norm & V4L2_STD_525_60)
213          */
214
215         if (dev->dev_type == TM6010) {
216                 tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
217                 tm6000_set_reg(dev, TM6010_REQ07_R41_TELETEXT_VBI_CODE1, 0x27);
218                 tm6000_set_reg(dev, TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55);
219                 tm6000_set_reg(dev, TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7, 0x66);
220                 tm6000_set_reg(dev, TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8, 0x66);
221                 tm6000_set_reg(dev, TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9, 0x66);
222                 tm6000_set_reg(dev,
223                         TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10, 0x66);
224                 tm6000_set_reg(dev,
225                         TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11, 0x66);
226                 tm6000_set_reg(dev,
227                         TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12, 0x66);
228                 tm6000_set_reg(dev,
229                         TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13, 0x66);
230                 tm6000_set_reg(dev,
231                         TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14, 0x66);
232                 tm6000_set_reg(dev,
233                         TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15, 0x66);
234                 tm6000_set_reg(dev,
235                         TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16, 0x66);
236                 tm6000_set_reg(dev,
237                         TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17, 0x66);
238                 tm6000_set_reg(dev,
239                         TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18, 0x66);
240                 tm6000_set_reg(dev,
241                         TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19, 0x66);
242                 tm6000_set_reg(dev,
243                         TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20, 0x66);
244                 tm6000_set_reg(dev,
245                         TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x66);
246                 tm6000_set_reg(dev,
247                         TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22, 0x66);
248                 tm6000_set_reg(dev,
249                         TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23, 0x00);
250                 tm6000_set_reg(dev,
251                         TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES, 0x00);
252                 tm6000_set_reg(dev,
253                         TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01);
254                 tm6000_set_reg(dev,
255                         TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN, 0x00);
256                 tm6000_set_reg(dev,
257                         TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02);
258                 tm6000_set_reg(dev, TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35);
259                 tm6000_set_reg(dev, TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0);
260                 tm6000_set_reg(dev, TM6010_REQ07_R5A_VBI_TELETEXT_DTO1, 0x11);
261                 tm6000_set_reg(dev, TM6010_REQ07_R5B_VBI_TELETEXT_DTO0, 0x4c);
262                 tm6000_set_reg(dev, TM6010_REQ07_R40_TELETEXT_VBI_CODE0, 0x01);
263                 tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
264         }
265 }
266
267 int tm6000_init_analog_mode(struct tm6000_core *dev)
268 {
269         struct v4l2_frequency f;
270
271         if (dev->dev_type == TM6010) {
272                 u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE;
273
274                 if (!dev->radio)
275                         active |= TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE;
276
277                 /* Enable video and audio */
278                 tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
279                                                         active, 0x60);
280                 /* Disable TS input */
281                 tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
282                                                         0x00, 0x40);
283         } else {
284                 /* Enables soft reset */
285                 tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
286
287                 if (dev->scaler)
288                         /* Disable Hfilter and Enable TS Drop err */
289                         tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20);
290                 else    /* Enable Hfilter and disable TS Drop err */
291                         tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80);
292
293                 tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88);
294                 tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x23);
295                 tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xc0);
296                 tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xd8);
297                 tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x06);
298                 tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f);
299
300                 /* AP Software reset */
301                 tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
302                 tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
303
304                 tm6000_set_fourcc_format(dev);
305
306                 /* Disables soft reset */
307                 tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
308         }
309         msleep(20);
310
311         /* Tuner firmware can now be loaded */
312
313         /*
314          * FIXME: This is a hack! xc3028 "sleeps" when no channel is detected
315          * for more than a few seconds. Not sure why, as this behavior does
316          * not happen on other devices with xc3028. So, I suspect that it
317          * is yet another bug at tm6000. After start sleeping, decoding
318          * doesn't start automatically. Instead, it requires some
319          * I2C commands to wake it up. As we want to have image at the
320          * beginning, we needed to add this hack. The better would be to
321          * discover some way to make tm6000 to wake up without this hack.
322          */
323         f.frequency = dev->freq;
324         v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
325
326         msleep(100);
327         tm6000_set_standard(dev);
328         tm6000_set_vbi(dev);
329         tm6000_set_audio_bitrate(dev, 48000);
330
331         /* switch dvb led off */
332         if (dev->gpio.dvb_led) {
333                 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
334                         dev->gpio.dvb_led, 0x01);
335         }
336
337         return 0;
338 }
339
340 int tm6000_init_digital_mode(struct tm6000_core *dev)
341 {
342         if (dev->dev_type == TM6010) {
343                 /* Disable video and audio */
344                 tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
345                                 0x00, 0x60);
346                 /* Enable TS input */
347                 tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
348                                 0x40, 0x40);
349                 /* all power down, but not the digital data port */
350                 tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0x28);
351                 tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc);
352                 tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff);
353         } else  {
354                 tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
355                 tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
356                 tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
357                 tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x08);
358                 tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
359                 tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
360                 tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0xd8);
361                 tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40);
362                 tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
363                 tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09);
364                 tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x37);
365                 tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xd8);
366                 tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xc0);
367                 tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x60);
368
369                 tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
370                 tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
371                 tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0x08);
372                 msleep(50);
373
374                 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
375                 msleep(50);
376                 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01);
377                 msleep(50);
378                 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
379                 msleep(100);
380         }
381
382         /* switch dvb led on */
383         if (dev->gpio.dvb_led) {
384                 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
385                         dev->gpio.dvb_led, 0x00);
386         }
387
388         return 0;
389 }
390 EXPORT_SYMBOL(tm6000_init_digital_mode);
391
392 struct reg_init {
393         u8 req;
394         u8 reg;
395         u8 val;
396 };
397
398 /* The meaning of those initializations are unknown */
399 static struct reg_init tm6000_init_tab[] = {
400         /* REG  VALUE */
401         { TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f },
402         { TM6010_REQ07_RFF_SOFT_RESET, 0x08 },
403         { TM6010_REQ07_RFF_SOFT_RESET, 0x00 },
404         { TM6010_REQ07_RD5_POWERSAVE, 0x4f },
405         { TM6000_REQ07_RDA_CLK_SEL, 0x23 },
406         { TM6000_REQ07_RDB_OUT_SEL, 0x08 },
407         { TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x00 },
408         { TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10 },
409         { TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00 },
410         { TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00 },
411         { TM6000_REQ07_REB_VADC_AADC_MODE, 0x64 },      /* 48000 bits/sample, external input */
412         { TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL, 0xc2 },
413
414         { TM6010_REQ07_R3F_RESET, 0x01 },               /* Start of soft reset */
415         { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
416         { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
417         { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
418         { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
419         { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
420         { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
421         { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
422         { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
423         { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
424         { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
425         { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
426         { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
427         { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
428         { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
429         { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
430         { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
431         { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
432         { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
433         { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
434         { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
435         { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
436         { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
437         { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
438         { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
439         { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
440         { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
441         { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
442         { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
443         { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
444         { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
445         { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
446         { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
447         { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
448         { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
449         { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
450         { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
451         { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
452         { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
453         { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
454         { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
455         { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
456         { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
457         { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
458         { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
459         { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
460         { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
461         { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
462         { TM6010_REQ07_RC3_HSTART1, 0x88 },
463         { TM6010_REQ07_R3F_RESET, 0x00 },               /* End of the soft reset */
464         { TM6010_REQ05_R18_IMASK7, 0x00 },
465 };
466
467 static struct reg_init tm6010_init_tab[] = {
468         { TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 },
469         { TM6010_REQ07_RC4_HSTART0, 0xa0 },
470         { TM6010_REQ07_RC6_HEND0, 0x40 },
471         { TM6010_REQ07_RCA_VEND0, 0x31 },
472         { TM6010_REQ07_RCC_ACTIVE_IF, 0xe1 },
473         { TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 },
474         { TM6010_REQ07_RFE_POWER_DOWN, 0x7f },
475
476         { TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0 },
477         { TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4 },
478         { TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8 },
479         { TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00 },
480         { TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2 },
481         { TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0 },
482         { TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2 },
483         { TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60 },
484         { TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc },
485
486         { TM6010_REQ07_R3F_RESET, 0x01 },
487         { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
488         { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
489         { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
490         { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
491         { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
492         { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
493         { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
494         { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
495         { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
496         { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
497         { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
498         { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
499         { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
500         { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
501         { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
502         { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
503         { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
504         { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
505         { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
506         { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
507         { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
508         { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
509         { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
510         { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
511         { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
512         { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
513         { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
514         { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
515         { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
516         { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
517         { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
518         { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
519         { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
520         { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
521         { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
522         { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
523         { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
524         { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
525         { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
526         { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
527         { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
528         { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
529         { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
530         { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
531         { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
532         { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
533         { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
534         { TM6010_REQ07_RC3_HSTART1, 0x88 },
535         { TM6010_REQ07_R3F_RESET, 0x00 },
536
537         { TM6010_REQ05_R18_IMASK7, 0x00 },
538
539         { TM6010_REQ07_RD8_IR_LEADER1, 0xaa },
540         { TM6010_REQ07_RD8_IR_LEADER0, 0x30 },
541         { TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20 },
542         { TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0 },
543         { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 },
544         { TM6010_REQ07_RD8_IR, 0x2f },
545
546         /* set remote wakeup key:any key wakeup */
547         { TM6010_REQ07_RE5_REMOTE_WAKEUP,  0xfe },
548         { TM6010_REQ07_RD8_IR_WAKEUP_SEL,  0xff },
549 };
550
551 int tm6000_init(struct tm6000_core *dev)
552 {
553         int board, rc = 0, i, size;
554         struct reg_init *tab;
555
556         /* Check board revision */
557         board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0);
558         if (board >= 0) {
559                 switch (board & 0xff) {
560                 case 0xf3:
561                         printk(KERN_INFO "Found tm6000\n");
562                         if (dev->dev_type != TM6000)
563                                 dev->dev_type = TM6000;
564                         break;
565                 case 0xf4:
566                         printk(KERN_INFO "Found tm6010\n");
567                         if (dev->dev_type != TM6010)
568                                 dev->dev_type = TM6010;
569                         break;
570                 default:
571                         printk(KERN_INFO "Unknown board version = 0x%08x\n", board);
572                 }
573         } else
574                 printk(KERN_ERR "Error %i while retrieving board version\n", board);
575
576         if (dev->dev_type == TM6010) {
577                 tab = tm6010_init_tab;
578                 size = ARRAY_SIZE(tm6010_init_tab);
579         } else {
580                 tab = tm6000_init_tab;
581                 size = ARRAY_SIZE(tm6000_init_tab);
582         }
583
584         /* Load board's initialization table */
585         for (i = 0; i < size; i++) {
586                 rc = tm6000_set_reg(dev, tab[i].req, tab[i].reg, tab[i].val);
587                 if (rc < 0) {
588                         printk(KERN_ERR "Error %i while setting req %d, "
589                                         "reg %d to value %d\n", rc,
590                                         tab[i].req, tab[i].reg, tab[i].val);
591                         return rc;
592                 }
593         }
594
595         msleep(5); /* Just to be conservative */
596
597         rc = tm6000_cards_setup(dev);
598
599         return rc;
600 }
601
602 int tm6000_reset(struct tm6000_core *dev)
603 {
604         int pipe;
605         int err;
606
607         msleep(500);
608
609         err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 0);
610         if (err < 0) {
611                 tm6000_err("failed to select interface %d, alt. setting 0\n",
612                                 dev->isoc_in.bInterfaceNumber);
613                 return err;
614         }
615
616         err = usb_reset_configuration(dev->udev);
617         if (err < 0) {
618                 tm6000_err("failed to reset configuration\n");
619                 return err;
620         }
621
622         msleep(5);
623
624         /*
625          * Not all devices have int_in defined
626          */
627         if (!dev->int_in.endp)
628                 return 0;
629
630         err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2);
631         if (err < 0) {
632                 tm6000_err("failed to select interface %d, alt. setting 2\n",
633                                 dev->isoc_in.bInterfaceNumber);
634                 return err;
635         }
636
637         msleep(5);
638
639         pipe = usb_rcvintpipe(dev->udev,
640                         dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
641
642         err = usb_clear_halt(dev->udev, pipe);
643         if (err < 0) {
644                 tm6000_err("usb_clear_halt failed: %d\n", err);
645                 return err;
646         }
647
648         return 0;
649 }
650
651 int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
652 {
653         int val = 0;
654         u8 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
655         u8 areg_0a = 0x91; /* SIF 48KHz */
656
657         switch (bitrate) {
658         case 48000:
659                 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
660                 areg_0a = 0x91; /* SIF 48KHz */
661                 dev->audio_bitrate = bitrate;
662                 break;
663         case 32000:
664                 areg_f0 = 0x00; /* ADC MCLK = 375 Fs */
665                 areg_0a = 0x90; /* SIF 32KHz */
666                 dev->audio_bitrate = bitrate;
667                 break;
668         default:
669                 return -EINVAL;
670         }
671
672
673         /* enable I2S, if we use sif or external I2S device */
674         if (dev->dev_type == TM6010) {
675                 val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, areg_0a);
676                 if (val < 0)
677                         return val;
678
679                 val = tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
680                                                         areg_f0, 0xf0);
681                 if (val < 0)
682                         return val;
683         } else {
684                 val = tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
685                                                         areg_f0, 0xf0);
686                 if (val < 0)
687                         return val;
688         }
689         return 0;
690 }
691 EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
692
693 int tm6000_set_audio_rinput(struct tm6000_core *dev)
694 {
695         if (dev->dev_type == TM6010) {
696                 /* Audio crossbar setting, default SIF1 */
697                 u8 areg_f0;
698
699                 switch (dev->rinput.amux) {
700                 case TM6000_AMUX_SIF1:
701                 case TM6000_AMUX_SIF2:
702                         areg_f0 = 0x03;
703                         break;
704                 case TM6000_AMUX_ADC1:
705                         areg_f0 = 0x00;
706                         break;
707                 case TM6000_AMUX_ADC2:
708                         areg_f0 = 0x08;
709                         break;
710                 case TM6000_AMUX_I2S:
711                         areg_f0 = 0x04;
712                         break;
713                 default:
714                         printk(KERN_INFO "%s: audio input dosn't support\n",
715                                 dev->name);
716                         return 0;
717                         break;
718                 }
719                 /* Set audio input crossbar */
720                 tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
721                                                         areg_f0, 0x0f);
722         } else {
723                 u8 areg_eb;
724                 /* Audio setting, default LINE1 */
725                 switch (dev->rinput.amux) {
726                 case TM6000_AMUX_ADC1:
727                         areg_eb = 0x00;
728                         break;
729                 case TM6000_AMUX_ADC2:
730                         areg_eb = 0x04;
731                         break;
732                 default:
733                         printk(KERN_INFO "%s: audio input dosn't support\n",
734                                 dev->name);
735                         return 0;
736                         break;
737                 }
738                 /* Set audio input */
739                 tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
740                                                         areg_eb, 0x0f);
741         }
742         return 0;
743 }
744
745 static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
746 {
747         u8 mute_reg = 0;
748
749         if (mute)
750                 mute_reg = 0x08;
751
752         tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08);
753 }
754
755 static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute)
756 {
757         u8 mute_reg = 0;
758
759         if (mute)
760                 mute_reg = 0x20;
761
762         if (dev->dev_type == TM6010) {
763                 tm6000_set_reg_mask(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL,
764                                                         mute_reg, 0x20);
765                 tm6000_set_reg_mask(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL,
766                                                         mute_reg, 0x20);
767         } else {
768                 tm6000_set_reg_mask(dev, TM6000_REQ07_REC_VADC_AADC_LVOL,
769                                                         mute_reg, 0x20);
770                 tm6000_set_reg_mask(dev, TM6000_REQ07_RED_VADC_AADC_RVOL,
771                                                         mute_reg, 0x20);
772         }
773 }
774
775 int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute)
776 {
777         enum tm6000_mux mux;
778
779         if (dev->radio)
780                 mux = dev->rinput.amux;
781         else
782                 mux = dev->vinput[dev->input].amux;
783
784         switch (mux) {
785         case TM6000_AMUX_SIF1:
786         case TM6000_AMUX_SIF2:
787                 if (dev->dev_type == TM6010)
788                         tm6010_set_mute_sif(dev, mute);
789                 else {
790                         printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
791                                         " SIF audio inputs. Please check the %s"
792                                         " configuration.\n", dev->name);
793                         return -EINVAL;
794                 }
795                 break;
796         case TM6000_AMUX_ADC1:
797         case TM6000_AMUX_ADC2:
798                 tm6010_set_mute_adc(dev, mute);
799                 break;
800         default:
801                 return -EINVAL;
802                 break;
803         }
804         return 0;
805 }
806
807 static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
808 {
809         u8 vol_reg;
810
811         vol_reg = vol & 0x0F;
812
813         if (vol < 0)
814                 vol_reg |= 0x40;
815
816         tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, vol_reg);
817         tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg);
818 }
819
820 static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol)
821 {
822         u8 vol_reg;
823
824         vol_reg = (vol + 0x10) & 0x1f;
825
826         if (dev->dev_type == TM6010) {
827                 tm6000_set_reg(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, vol_reg);
828                 tm6000_set_reg(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, vol_reg);
829         } else {
830                 tm6000_set_reg(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, vol_reg);
831                 tm6000_set_reg(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, vol_reg);
832         }
833 }
834
835 void tm6000_set_volume(struct tm6000_core *dev, int vol)
836 {
837         enum tm6000_mux mux;
838
839         if (dev->radio) {
840                 mux = dev->rinput.amux;
841                 vol += 8; /* Offset to 0 dB */
842         } else
843                 mux = dev->vinput[dev->input].amux;
844
845         switch (mux) {
846         case TM6000_AMUX_SIF1:
847         case TM6000_AMUX_SIF2:
848                 if (dev->dev_type == TM6010)
849                         tm6010_set_volume_sif(dev, vol);
850                 else
851                         printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
852                                         " SIF audio inputs. Please check the %s"
853                                         " configuration.\n", dev->name);
854                 break;
855         case TM6000_AMUX_ADC1:
856         case TM6000_AMUX_ADC2:
857                 tm6010_set_volume_adc(dev, vol);
858                 break;
859         default:
860                 break;
861         }
862 }
863
864 static LIST_HEAD(tm6000_devlist);
865 static DEFINE_MUTEX(tm6000_devlist_mutex);
866
867 /*
868  * tm6000_realease_resource()
869  */
870
871 void tm6000_remove_from_devlist(struct tm6000_core *dev)
872 {
873         mutex_lock(&tm6000_devlist_mutex);
874         list_del(&dev->devlist);
875         mutex_unlock(&tm6000_devlist_mutex);
876 };
877
878 void tm6000_add_into_devlist(struct tm6000_core *dev)
879 {
880         mutex_lock(&tm6000_devlist_mutex);
881         list_add_tail(&dev->devlist, &tm6000_devlist);
882         mutex_unlock(&tm6000_devlist_mutex);
883 };
884
885 /*
886  * Extension interface
887  */
888
889 static LIST_HEAD(tm6000_extension_devlist);
890
891 int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
892                         char *buf, int size)
893 {
894         struct tm6000_ops *ops = NULL;
895
896         /* FIXME: tm6000_extension_devlist_lock should be a spinlock */
897
898         if (!list_empty(&tm6000_extension_devlist)) {
899                 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
900                         if (ops->fillbuf && ops->type == type)
901                                 ops->fillbuf(dev, buf, size);
902                 }
903         }
904
905         return 0;
906 }
907
908 int tm6000_register_extension(struct tm6000_ops *ops)
909 {
910         struct tm6000_core *dev = NULL;
911
912         mutex_lock(&tm6000_devlist_mutex);
913         list_add_tail(&ops->next, &tm6000_extension_devlist);
914         list_for_each_entry(dev, &tm6000_devlist, devlist) {
915                 ops->init(dev);
916                 printk(KERN_INFO "%s: Initialized (%s) extension\n",
917                        dev->name, ops->name);
918         }
919         mutex_unlock(&tm6000_devlist_mutex);
920         return 0;
921 }
922 EXPORT_SYMBOL(tm6000_register_extension);
923
924 void tm6000_unregister_extension(struct tm6000_ops *ops)
925 {
926         struct tm6000_core *dev = NULL;
927
928         mutex_lock(&tm6000_devlist_mutex);
929         list_for_each_entry(dev, &tm6000_devlist, devlist)
930                 ops->fini(dev);
931
932         printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
933         list_del(&ops->next);
934         mutex_unlock(&tm6000_devlist_mutex);
935 }
936 EXPORT_SYMBOL(tm6000_unregister_extension);
937
938 void tm6000_init_extension(struct tm6000_core *dev)
939 {
940         struct tm6000_ops *ops = NULL;
941
942         mutex_lock(&tm6000_devlist_mutex);
943         if (!list_empty(&tm6000_extension_devlist)) {
944                 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
945                         if (ops->init)
946                                 ops->init(dev);
947                 }
948         }
949         mutex_unlock(&tm6000_devlist_mutex);
950 }
951
952 void tm6000_close_extension(struct tm6000_core *dev)
953 {
954         struct tm6000_ops *ops = NULL;
955
956         mutex_lock(&tm6000_devlist_mutex);
957         if (!list_empty(&tm6000_extension_devlist)) {
958                 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
959                         if (ops->fini)
960                                 ops->fini(dev);
961                 }
962         }
963         mutex_unlock(&tm6000_devlist_mutex);
964 }