6d0803c886be3197ddb3dd63fbb25acea7d50be2
[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         if ((dev->quirks & TM6000_QUIRK_NO_USB_DELAY) == 0)
623                 msleep(5);
624
625         /*
626          * Not all devices have int_in defined
627          */
628         if (!dev->int_in.endp)
629                 return 0;
630
631         err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2);
632         if (err < 0) {
633                 tm6000_err("failed to select interface %d, alt. setting 2\n",
634                                 dev->isoc_in.bInterfaceNumber);
635                 return err;
636         }
637
638         msleep(5);
639
640         pipe = usb_rcvintpipe(dev->udev,
641                         dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
642
643         err = usb_clear_halt(dev->udev, pipe);
644         if (err < 0) {
645                 tm6000_err("usb_clear_halt failed: %d\n", err);
646                 return err;
647         }
648
649         return 0;
650 }
651
652 int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
653 {
654         int val = 0;
655         u8 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
656         u8 areg_0a = 0x91; /* SIF 48KHz */
657
658         switch (bitrate) {
659         case 48000:
660                 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
661                 areg_0a = 0x91; /* SIF 48KHz */
662                 dev->audio_bitrate = bitrate;
663                 break;
664         case 32000:
665                 areg_f0 = 0x00; /* ADC MCLK = 375 Fs */
666                 areg_0a = 0x90; /* SIF 32KHz */
667                 dev->audio_bitrate = bitrate;
668                 break;
669         default:
670                 return -EINVAL;
671         }
672
673
674         /* enable I2S, if we use sif or external I2S device */
675         if (dev->dev_type == TM6010) {
676                 val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, areg_0a);
677                 if (val < 0)
678                         return val;
679
680                 val = tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
681                                                         areg_f0, 0xf0);
682                 if (val < 0)
683                         return val;
684         } else {
685                 val = tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
686                                                         areg_f0, 0xf0);
687                 if (val < 0)
688                         return val;
689         }
690         return 0;
691 }
692 EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
693
694 int tm6000_set_audio_rinput(struct tm6000_core *dev)
695 {
696         if (dev->dev_type == TM6010) {
697                 /* Audio crossbar setting, default SIF1 */
698                 u8 areg_f0;
699
700                 switch (dev->rinput.amux) {
701                 case TM6000_AMUX_SIF1:
702                 case TM6000_AMUX_SIF2:
703                         areg_f0 = 0x03;
704                         break;
705                 case TM6000_AMUX_ADC1:
706                         areg_f0 = 0x00;
707                         break;
708                 case TM6000_AMUX_ADC2:
709                         areg_f0 = 0x08;
710                         break;
711                 case TM6000_AMUX_I2S:
712                         areg_f0 = 0x04;
713                         break;
714                 default:
715                         printk(KERN_INFO "%s: audio input dosn't support\n",
716                                 dev->name);
717                         return 0;
718                         break;
719                 }
720                 /* Set audio input crossbar */
721                 tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
722                                                         areg_f0, 0x0f);
723         } else {
724                 u8 areg_eb;
725                 /* Audio setting, default LINE1 */
726                 switch (dev->rinput.amux) {
727                 case TM6000_AMUX_ADC1:
728                         areg_eb = 0x00;
729                         break;
730                 case TM6000_AMUX_ADC2:
731                         areg_eb = 0x04;
732                         break;
733                 default:
734                         printk(KERN_INFO "%s: audio input dosn't support\n",
735                                 dev->name);
736                         return 0;
737                         break;
738                 }
739                 /* Set audio input */
740                 tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
741                                                         areg_eb, 0x0f);
742         }
743         return 0;
744 }
745
746 static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
747 {
748         u8 mute_reg = 0;
749
750         if (mute)
751                 mute_reg = 0x08;
752
753         tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08);
754 }
755
756 static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute)
757 {
758         u8 mute_reg = 0;
759
760         if (mute)
761                 mute_reg = 0x20;
762
763         if (dev->dev_type == TM6010) {
764                 tm6000_set_reg_mask(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL,
765                                                         mute_reg, 0x20);
766                 tm6000_set_reg_mask(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL,
767                                                         mute_reg, 0x20);
768         } else {
769                 tm6000_set_reg_mask(dev, TM6000_REQ07_REC_VADC_AADC_LVOL,
770                                                         mute_reg, 0x20);
771                 tm6000_set_reg_mask(dev, TM6000_REQ07_RED_VADC_AADC_RVOL,
772                                                         mute_reg, 0x20);
773         }
774 }
775
776 int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute)
777 {
778         enum tm6000_mux mux;
779
780         if (dev->radio)
781                 mux = dev->rinput.amux;
782         else
783                 mux = dev->vinput[dev->input].amux;
784
785         switch (mux) {
786         case TM6000_AMUX_SIF1:
787         case TM6000_AMUX_SIF2:
788                 if (dev->dev_type == TM6010)
789                         tm6010_set_mute_sif(dev, mute);
790                 else {
791                         printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
792                                         " SIF audio inputs. Please check the %s"
793                                         " configuration.\n", dev->name);
794                         return -EINVAL;
795                 }
796                 break;
797         case TM6000_AMUX_ADC1:
798         case TM6000_AMUX_ADC2:
799                 tm6010_set_mute_adc(dev, mute);
800                 break;
801         default:
802                 return -EINVAL;
803                 break;
804         }
805         return 0;
806 }
807
808 static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
809 {
810         u8 vol_reg;
811
812         vol_reg = vol & 0x0F;
813
814         if (vol < 0)
815                 vol_reg |= 0x40;
816
817         tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, vol_reg);
818         tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg);
819 }
820
821 static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol)
822 {
823         u8 vol_reg;
824
825         vol_reg = (vol + 0x10) & 0x1f;
826
827         if (dev->dev_type == TM6010) {
828                 tm6000_set_reg(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, vol_reg);
829                 tm6000_set_reg(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, vol_reg);
830         } else {
831                 tm6000_set_reg(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, vol_reg);
832                 tm6000_set_reg(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, vol_reg);
833         }
834 }
835
836 void tm6000_set_volume(struct tm6000_core *dev, int vol)
837 {
838         enum tm6000_mux mux;
839
840         if (dev->radio) {
841                 mux = dev->rinput.amux;
842                 vol += 8; /* Offset to 0 dB */
843         } else
844                 mux = dev->vinput[dev->input].amux;
845
846         switch (mux) {
847         case TM6000_AMUX_SIF1:
848         case TM6000_AMUX_SIF2:
849                 if (dev->dev_type == TM6010)
850                         tm6010_set_volume_sif(dev, vol);
851                 else
852                         printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
853                                         " SIF audio inputs. Please check the %s"
854                                         " configuration.\n", dev->name);
855                 break;
856         case TM6000_AMUX_ADC1:
857         case TM6000_AMUX_ADC2:
858                 tm6010_set_volume_adc(dev, vol);
859                 break;
860         default:
861                 break;
862         }
863 }
864
865 static LIST_HEAD(tm6000_devlist);
866 static DEFINE_MUTEX(tm6000_devlist_mutex);
867
868 /*
869  * tm6000_realease_resource()
870  */
871
872 void tm6000_remove_from_devlist(struct tm6000_core *dev)
873 {
874         mutex_lock(&tm6000_devlist_mutex);
875         list_del(&dev->devlist);
876         mutex_unlock(&tm6000_devlist_mutex);
877 };
878
879 void tm6000_add_into_devlist(struct tm6000_core *dev)
880 {
881         mutex_lock(&tm6000_devlist_mutex);
882         list_add_tail(&dev->devlist, &tm6000_devlist);
883         mutex_unlock(&tm6000_devlist_mutex);
884 };
885
886 /*
887  * Extension interface
888  */
889
890 static LIST_HEAD(tm6000_extension_devlist);
891
892 int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
893                         char *buf, int size)
894 {
895         struct tm6000_ops *ops = NULL;
896
897         /* FIXME: tm6000_extension_devlist_lock should be a spinlock */
898
899         if (!list_empty(&tm6000_extension_devlist)) {
900                 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
901                         if (ops->fillbuf && ops->type == type)
902                                 ops->fillbuf(dev, buf, size);
903                 }
904         }
905
906         return 0;
907 }
908
909 int tm6000_register_extension(struct tm6000_ops *ops)
910 {
911         struct tm6000_core *dev = NULL;
912
913         mutex_lock(&tm6000_devlist_mutex);
914         list_add_tail(&ops->next, &tm6000_extension_devlist);
915         list_for_each_entry(dev, &tm6000_devlist, devlist) {
916                 ops->init(dev);
917                 printk(KERN_INFO "%s: Initialized (%s) extension\n",
918                        dev->name, ops->name);
919         }
920         mutex_unlock(&tm6000_devlist_mutex);
921         return 0;
922 }
923 EXPORT_SYMBOL(tm6000_register_extension);
924
925 void tm6000_unregister_extension(struct tm6000_ops *ops)
926 {
927         struct tm6000_core *dev = NULL;
928
929         mutex_lock(&tm6000_devlist_mutex);
930         list_for_each_entry(dev, &tm6000_devlist, devlist)
931                 ops->fini(dev);
932
933         printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
934         list_del(&ops->next);
935         mutex_unlock(&tm6000_devlist_mutex);
936 }
937 EXPORT_SYMBOL(tm6000_unregister_extension);
938
939 void tm6000_init_extension(struct tm6000_core *dev)
940 {
941         struct tm6000_ops *ops = NULL;
942
943         mutex_lock(&tm6000_devlist_mutex);
944         if (!list_empty(&tm6000_extension_devlist)) {
945                 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
946                         if (ops->init)
947                                 ops->init(dev);
948                 }
949         }
950         mutex_unlock(&tm6000_devlist_mutex);
951 }
952
953 void tm6000_close_extension(struct tm6000_core *dev)
954 {
955         struct tm6000_ops *ops = NULL;
956
957         mutex_lock(&tm6000_devlist_mutex);
958         if (!list_empty(&tm6000_extension_devlist)) {
959                 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
960                         if (ops->fini)
961                                 ops->fini(dev);
962                 }
963         }
964         mutex_unlock(&tm6000_devlist_mutex);
965 }