0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/slab.h>
0012 #include <linux/usb.h>
0013 #include <linux/i2c.h>
0014 #include "tm6000.h"
0015 #include "tm6000-regs.h"
0016 #include <media/v4l2-common.h>
0017 #include <media/tuner.h>
0018
0019 #define USB_TIMEOUT (5 * HZ)
0020
0021 int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
0022 u16 value, u16 index, u8 *buf, u16 len)
0023 {
0024 int ret, i;
0025 unsigned int pipe;
0026 u8 *data = NULL;
0027 int delay = 5000;
0028
0029 if (len) {
0030 data = kzalloc(len, GFP_KERNEL);
0031 if (!data)
0032 return -ENOMEM;
0033 }
0034
0035 mutex_lock(&dev->usb_lock);
0036
0037 if (req_type & USB_DIR_IN)
0038 pipe = usb_rcvctrlpipe(dev->udev, 0);
0039 else {
0040 pipe = usb_sndctrlpipe(dev->udev, 0);
0041 memcpy(data, buf, len);
0042 }
0043
0044 if (tm6000_debug & V4L2_DEBUG_I2C) {
0045 printk(KERN_DEBUG "(dev %p, pipe %08x): ", dev->udev, pipe);
0046
0047 printk(KERN_CONT "%s: %02x %02x %02x %02x %02x %02x %02x %02x ",
0048 (req_type & USB_DIR_IN) ? " IN" : "OUT",
0049 req_type, req, value&0xff, value>>8, index&0xff,
0050 index>>8, len&0xff, len>>8);
0051
0052 if (!(req_type & USB_DIR_IN)) {
0053 printk(KERN_CONT ">>> ");
0054 for (i = 0; i < len; i++)
0055 printk(KERN_CONT " %02x", buf[i]);
0056 printk(KERN_CONT "\n");
0057 }
0058 }
0059
0060 ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index,
0061 data, len, USB_TIMEOUT);
0062
0063 if (req_type & USB_DIR_IN)
0064 memcpy(buf, data, len);
0065
0066 if (tm6000_debug & V4L2_DEBUG_I2C) {
0067 if (ret < 0) {
0068 if (req_type & USB_DIR_IN)
0069 printk(KERN_DEBUG "<<< (len=%d)\n", len);
0070
0071 printk(KERN_CONT "%s: Error #%d\n", __func__, ret);
0072 } else if (req_type & USB_DIR_IN) {
0073 printk(KERN_CONT "<<< ");
0074 for (i = 0; i < len; i++)
0075 printk(KERN_CONT " %02x", buf[i]);
0076 printk(KERN_CONT "\n");
0077 }
0078 }
0079
0080 kfree(data);
0081
0082 if (dev->quirks & TM6000_QUIRK_NO_USB_DELAY)
0083 delay = 0;
0084
0085 if (req == REQ_16_SET_GET_I2C_WR1_RDN && !(req_type & USB_DIR_IN)) {
0086 unsigned int tsleep;
0087
0088 tsleep = (len * 200) + 200;
0089 if (tsleep < delay)
0090 tsleep = delay;
0091 usleep_range(tsleep, tsleep + 1000);
0092 }
0093 else if (delay)
0094 usleep_range(delay, delay + 1000);
0095
0096 mutex_unlock(&dev->usb_lock);
0097 return ret;
0098 }
0099
0100 int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
0101 {
0102 return
0103 tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
0104 req, value, index, NULL, 0);
0105 }
0106 EXPORT_SYMBOL_GPL(tm6000_set_reg);
0107
0108 int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
0109 {
0110 int rc;
0111 u8 buf[1];
0112
0113 rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
0114 value, index, buf, 1);
0115
0116 if (rc < 0)
0117 return rc;
0118
0119 return *buf;
0120 }
0121 EXPORT_SYMBOL_GPL(tm6000_get_reg);
0122
0123 int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
0124 u16 index, u16 mask)
0125 {
0126 int rc;
0127 u8 buf[1];
0128 u8 new_index;
0129
0130 rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
0131 value, 0, buf, 1);
0132
0133 if (rc < 0)
0134 return rc;
0135
0136 new_index = (buf[0] & ~mask) | (index & mask);
0137
0138 if (new_index == buf[0])
0139 return 0;
0140
0141 return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
0142 req, value, new_index, NULL, 0);
0143 }
0144 EXPORT_SYMBOL_GPL(tm6000_set_reg_mask);
0145
0146 int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index)
0147 {
0148 int rc;
0149 u8 buf[2];
0150
0151 rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
0152 value, index, buf, 2);
0153
0154 if (rc < 0)
0155 return rc;
0156
0157 return buf[1]|buf[0]<<8;
0158 }
0159
0160 int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index)
0161 {
0162 int rc;
0163 u8 buf[4];
0164
0165 rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
0166 value, index, buf, 4);
0167
0168 if (rc < 0)
0169 return rc;
0170
0171 return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
0172 }
0173
0174 int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep)
0175 {
0176 int rc;
0177
0178 rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
0179 if (rc < 0)
0180 return rc;
0181
0182 msleep(tsleep);
0183
0184 rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
0185 msleep(tsleep);
0186
0187 return rc;
0188 }
0189
0190 void tm6000_set_fourcc_format(struct tm6000_core *dev)
0191 {
0192 if (dev->dev_type == TM6010) {
0193 int val;
0194
0195 val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, 0) & 0xfc;
0196 if (dev->fourcc == V4L2_PIX_FMT_UYVY)
0197 tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val);
0198 else
0199 tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val | 1);
0200 } else {
0201 if (dev->fourcc == V4L2_PIX_FMT_UYVY)
0202 tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
0203 else
0204 tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0x90);
0205 }
0206 }
0207
0208 static void tm6000_set_vbi(struct tm6000_core *dev)
0209 {
0210
0211
0212
0213
0214
0215
0216
0217
0218 if (dev->dev_type == TM6010) {
0219 tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
0220 tm6000_set_reg(dev, TM6010_REQ07_R41_TELETEXT_VBI_CODE1, 0x27);
0221 tm6000_set_reg(dev, TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55);
0222 tm6000_set_reg(dev, TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7, 0x66);
0223 tm6000_set_reg(dev, TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8, 0x66);
0224 tm6000_set_reg(dev, TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9, 0x66);
0225 tm6000_set_reg(dev,
0226 TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10, 0x66);
0227 tm6000_set_reg(dev,
0228 TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11, 0x66);
0229 tm6000_set_reg(dev,
0230 TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12, 0x66);
0231 tm6000_set_reg(dev,
0232 TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13, 0x66);
0233 tm6000_set_reg(dev,
0234 TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14, 0x66);
0235 tm6000_set_reg(dev,
0236 TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15, 0x66);
0237 tm6000_set_reg(dev,
0238 TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16, 0x66);
0239 tm6000_set_reg(dev,
0240 TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17, 0x66);
0241 tm6000_set_reg(dev,
0242 TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18, 0x66);
0243 tm6000_set_reg(dev,
0244 TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19, 0x66);
0245 tm6000_set_reg(dev,
0246 TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20, 0x66);
0247 tm6000_set_reg(dev,
0248 TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x66);
0249 tm6000_set_reg(dev,
0250 TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22, 0x66);
0251 tm6000_set_reg(dev,
0252 TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23, 0x00);
0253 tm6000_set_reg(dev,
0254 TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES, 0x00);
0255 tm6000_set_reg(dev,
0256 TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01);
0257 tm6000_set_reg(dev,
0258 TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN, 0x00);
0259 tm6000_set_reg(dev,
0260 TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02);
0261 tm6000_set_reg(dev, TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35);
0262 tm6000_set_reg(dev, TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0);
0263 tm6000_set_reg(dev, TM6010_REQ07_R5A_VBI_TELETEXT_DTO1, 0x11);
0264 tm6000_set_reg(dev, TM6010_REQ07_R5B_VBI_TELETEXT_DTO0, 0x4c);
0265 tm6000_set_reg(dev, TM6010_REQ07_R40_TELETEXT_VBI_CODE0, 0x01);
0266 tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
0267 }
0268 }
0269
0270 int tm6000_init_analog_mode(struct tm6000_core *dev)
0271 {
0272 struct v4l2_frequency f;
0273
0274 if (dev->dev_type == TM6010) {
0275 u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE;
0276
0277 if (!dev->radio)
0278 active |= TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE;
0279
0280
0281 tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
0282 active, 0x60);
0283
0284 tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
0285 0x00, 0x40);
0286 } else {
0287
0288 tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
0289
0290 if (dev->scaler)
0291
0292 tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20);
0293 else
0294 tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80);
0295
0296 tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88);
0297 tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x23);
0298 tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xc0);
0299 tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xd8);
0300 tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x06);
0301 tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f);
0302
0303
0304 tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
0305 tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
0306
0307 tm6000_set_fourcc_format(dev);
0308
0309
0310 tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
0311 }
0312 msleep(20);
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326 f.frequency = dev->freq;
0327 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
0328
0329 msleep(100);
0330 tm6000_set_standard(dev);
0331 tm6000_set_vbi(dev);
0332 tm6000_set_audio_bitrate(dev, 48000);
0333
0334
0335 if (dev->gpio.dvb_led) {
0336 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
0337 dev->gpio.dvb_led, 0x01);
0338 }
0339
0340 return 0;
0341 }
0342
0343 int tm6000_init_digital_mode(struct tm6000_core *dev)
0344 {
0345 if (dev->dev_type == TM6010) {
0346
0347 tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
0348 0x00, 0x60);
0349
0350 tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
0351 0x40, 0x40);
0352
0353 tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0x28);
0354 tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc);
0355 tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff);
0356 } else {
0357 tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
0358 tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
0359 tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
0360 tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x08);
0361 tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
0362 tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
0363 tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0xd8);
0364 tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40);
0365 tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
0366 tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09);
0367 tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x37);
0368 tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xd8);
0369 tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xc0);
0370 tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x60);
0371
0372 tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
0373 tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
0374 tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0x08);
0375 msleep(50);
0376
0377 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
0378 msleep(50);
0379 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01);
0380 msleep(50);
0381 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
0382 msleep(100);
0383 }
0384
0385
0386 if (dev->gpio.dvb_led) {
0387 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
0388 dev->gpio.dvb_led, 0x00);
0389 }
0390
0391 return 0;
0392 }
0393 EXPORT_SYMBOL(tm6000_init_digital_mode);
0394
0395 struct reg_init {
0396 u8 req;
0397 u8 reg;
0398 u8 val;
0399 };
0400
0401
0402 static struct reg_init tm6000_init_tab[] = {
0403
0404 { TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f },
0405 { TM6010_REQ07_RFF_SOFT_RESET, 0x08 },
0406 { TM6010_REQ07_RFF_SOFT_RESET, 0x00 },
0407 { TM6010_REQ07_RD5_POWERSAVE, 0x4f },
0408 { TM6000_REQ07_RDA_CLK_SEL, 0x23 },
0409 { TM6000_REQ07_RDB_OUT_SEL, 0x08 },
0410 { TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x00 },
0411 { TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10 },
0412 { TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00 },
0413 { TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00 },
0414 { TM6000_REQ07_REB_VADC_AADC_MODE, 0x64 },
0415 { TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL, 0xc2 },
0416
0417 { TM6010_REQ07_R3F_RESET, 0x01 },
0418 { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
0419 { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
0420 { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
0421 { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
0422 { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
0423 { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
0424 { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
0425 { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
0426 { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
0427 { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
0428 { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
0429 { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
0430 { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
0431 { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
0432 { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
0433 { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
0434 { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
0435 { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
0436 { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
0437 { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
0438 { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
0439 { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
0440 { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
0441 { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
0442 { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
0443 { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
0444 { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
0445 { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
0446 { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
0447 { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
0448 { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
0449 { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
0450 { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
0451 { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
0452 { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
0453 { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
0454 { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
0455 { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
0456 { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
0457 { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
0458 { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
0459 { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
0460 { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
0461 { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
0462 { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
0463 { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
0464 { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
0465 { TM6010_REQ07_RC3_HSTART1, 0x88 },
0466 { TM6010_REQ07_R3F_RESET, 0x00 },
0467 { TM6010_REQ05_R18_IMASK7, 0x00 },
0468 };
0469
0470 static struct reg_init tm6010_init_tab[] = {
0471 { TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 },
0472 { TM6010_REQ07_RC4_HSTART0, 0xa0 },
0473 { TM6010_REQ07_RC6_HEND0, 0x40 },
0474 { TM6010_REQ07_RCA_VEND0, 0x31 },
0475 { TM6010_REQ07_RCC_ACTIVE_IF, 0xe1 },
0476 { TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 },
0477 { TM6010_REQ07_RFE_POWER_DOWN, 0x7f },
0478
0479 { TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0 },
0480 { TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4 },
0481 { TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8 },
0482 { TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00 },
0483 { TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2 },
0484 { TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0 },
0485 { TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2 },
0486 { TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60 },
0487 { TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc },
0488
0489 { TM6010_REQ07_R3F_RESET, 0x01 },
0490 { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
0491 { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
0492 { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
0493 { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
0494 { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
0495 { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
0496 { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
0497 { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
0498 { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
0499 { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
0500 { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
0501 { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
0502 { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
0503 { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
0504 { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
0505 { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
0506 { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
0507 { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
0508 { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
0509 { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
0510 { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
0511 { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
0512 { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
0513 { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
0514 { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
0515 { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
0516 { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
0517 { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
0518 { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
0519 { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
0520 { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
0521 { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
0522 { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
0523 { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
0524 { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
0525 { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
0526 { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
0527 { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
0528 { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
0529 { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
0530 { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
0531 { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
0532 { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
0533 { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
0534 { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
0535 { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
0536 { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
0537 { TM6010_REQ07_RC3_HSTART1, 0x88 },
0538 { TM6010_REQ07_R3F_RESET, 0x00 },
0539
0540 { TM6010_REQ05_R18_IMASK7, 0x00 },
0541
0542 { TM6010_REQ07_RDC_IR_LEADER1, 0xaa },
0543 { TM6010_REQ07_RDD_IR_LEADER0, 0x30 },
0544 { TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20 },
0545 { TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0 },
0546 { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 },
0547 { TM6010_REQ07_RD8_IR, 0x0f },
0548
0549
0550 { TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe },
0551 { TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff },
0552 };
0553
0554 int tm6000_init(struct tm6000_core *dev)
0555 {
0556 int board, rc = 0, i, size;
0557 struct reg_init *tab;
0558
0559
0560 board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0);
0561 if (board >= 0) {
0562 switch (board & 0xff) {
0563 case 0xf3:
0564 printk(KERN_INFO "Found tm6000\n");
0565 if (dev->dev_type != TM6000)
0566 dev->dev_type = TM6000;
0567 break;
0568 case 0xf4:
0569 printk(KERN_INFO "Found tm6010\n");
0570 if (dev->dev_type != TM6010)
0571 dev->dev_type = TM6010;
0572 break;
0573 default:
0574 printk(KERN_INFO "Unknown board version = 0x%08x\n", board);
0575 }
0576 } else
0577 printk(KERN_ERR "Error %i while retrieving board version\n", board);
0578
0579 if (dev->dev_type == TM6010) {
0580 tab = tm6010_init_tab;
0581 size = ARRAY_SIZE(tm6010_init_tab);
0582 } else {
0583 tab = tm6000_init_tab;
0584 size = ARRAY_SIZE(tm6000_init_tab);
0585 }
0586
0587
0588 for (i = 0; i < size; i++) {
0589 rc = tm6000_set_reg(dev, tab[i].req, tab[i].reg, tab[i].val);
0590 if (rc < 0) {
0591 printk(KERN_ERR "Error %i while setting req %d, reg %d to value %d\n",
0592 rc,
0593 tab[i].req, tab[i].reg, tab[i].val);
0594 return rc;
0595 }
0596 }
0597
0598 msleep(5);
0599
0600 rc = tm6000_cards_setup(dev);
0601
0602 return rc;
0603 }
0604
0605
0606 int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
0607 {
0608 int val = 0;
0609 u8 areg_f0 = 0x60;
0610 u8 areg_0a = 0x91;
0611
0612 switch (bitrate) {
0613 case 48000:
0614 areg_f0 = 0x60;
0615 areg_0a = 0x91;
0616 dev->audio_bitrate = bitrate;
0617 break;
0618 case 32000:
0619 areg_f0 = 0x00;
0620 areg_0a = 0x90;
0621 dev->audio_bitrate = bitrate;
0622 break;
0623 default:
0624 return -EINVAL;
0625 }
0626
0627
0628
0629 if (dev->dev_type == TM6010) {
0630 val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, areg_0a);
0631 if (val < 0)
0632 return val;
0633
0634 val = tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
0635 areg_f0, 0xf0);
0636 if (val < 0)
0637 return val;
0638 } else {
0639 val = tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
0640 areg_f0, 0xf0);
0641 if (val < 0)
0642 return val;
0643 }
0644 return 0;
0645 }
0646 EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
0647
0648 int tm6000_set_audio_rinput(struct tm6000_core *dev)
0649 {
0650 if (dev->dev_type == TM6010) {
0651
0652 u8 areg_f0;
0653 u8 areg_07 = 0x10;
0654
0655 switch (dev->rinput.amux) {
0656 case TM6000_AMUX_SIF1:
0657 case TM6000_AMUX_SIF2:
0658 areg_f0 = 0x03;
0659 areg_07 = 0x30;
0660 break;
0661 case TM6000_AMUX_ADC1:
0662 areg_f0 = 0x00;
0663 break;
0664 case TM6000_AMUX_ADC2:
0665 areg_f0 = 0x08;
0666 break;
0667 case TM6000_AMUX_I2S:
0668 areg_f0 = 0x04;
0669 break;
0670 default:
0671 printk(KERN_INFO "%s: audio input doesn't support\n",
0672 dev->name);
0673 return 0;
0674 break;
0675 }
0676
0677 tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
0678 areg_f0, 0x0f);
0679
0680 tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
0681 areg_07, 0xf0);
0682 } else {
0683 u8 areg_eb;
0684
0685 switch (dev->rinput.amux) {
0686 case TM6000_AMUX_ADC1:
0687 areg_eb = 0x00;
0688 break;
0689 case TM6000_AMUX_ADC2:
0690 areg_eb = 0x04;
0691 break;
0692 default:
0693 printk(KERN_INFO "%s: audio input doesn't support\n",
0694 dev->name);
0695 return 0;
0696 break;
0697 }
0698
0699 tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
0700 areg_eb, 0x0f);
0701 }
0702 return 0;
0703 }
0704
0705 static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
0706 {
0707 u8 mute_reg = 0;
0708
0709 if (mute)
0710 mute_reg = 0x08;
0711
0712 tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08);
0713 }
0714
0715 static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute)
0716 {
0717 u8 mute_reg = 0;
0718
0719 if (mute)
0720 mute_reg = 0x20;
0721
0722 if (dev->dev_type == TM6010) {
0723 tm6000_set_reg_mask(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL,
0724 mute_reg, 0x20);
0725 tm6000_set_reg_mask(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL,
0726 mute_reg, 0x20);
0727 } else {
0728 tm6000_set_reg_mask(dev, TM6000_REQ07_REC_VADC_AADC_LVOL,
0729 mute_reg, 0x20);
0730 tm6000_set_reg_mask(dev, TM6000_REQ07_RED_VADC_AADC_RVOL,
0731 mute_reg, 0x20);
0732 }
0733 }
0734
0735 int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute)
0736 {
0737 enum tm6000_mux mux;
0738
0739 if (dev->radio)
0740 mux = dev->rinput.amux;
0741 else
0742 mux = dev->vinput[dev->input].amux;
0743
0744 switch (mux) {
0745 case TM6000_AMUX_SIF1:
0746 case TM6000_AMUX_SIF2:
0747 if (dev->dev_type == TM6010)
0748 tm6010_set_mute_sif(dev, mute);
0749 else {
0750 printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has SIF audio inputs. Please check the %s configuration.\n",
0751 dev->name);
0752 return -EINVAL;
0753 }
0754 break;
0755 case TM6000_AMUX_ADC1:
0756 case TM6000_AMUX_ADC2:
0757 tm6010_set_mute_adc(dev, mute);
0758 break;
0759 default:
0760 return -EINVAL;
0761 break;
0762 }
0763 return 0;
0764 }
0765
0766 static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
0767 {
0768 u8 vol_reg;
0769
0770 vol_reg = vol & 0x0F;
0771
0772 if (vol < 0)
0773 vol_reg |= 0x40;
0774
0775 tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, vol_reg);
0776 tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg);
0777 }
0778
0779 static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol)
0780 {
0781 u8 vol_reg;
0782
0783 vol_reg = (vol + 0x10) & 0x1f;
0784
0785 if (dev->dev_type == TM6010) {
0786 tm6000_set_reg(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, vol_reg);
0787 tm6000_set_reg(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, vol_reg);
0788 } else {
0789 tm6000_set_reg(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, vol_reg);
0790 tm6000_set_reg(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, vol_reg);
0791 }
0792 }
0793
0794 void tm6000_set_volume(struct tm6000_core *dev, int vol)
0795 {
0796 enum tm6000_mux mux;
0797
0798 if (dev->radio) {
0799 mux = dev->rinput.amux;
0800 vol += 8;
0801 } else
0802 mux = dev->vinput[dev->input].amux;
0803
0804 switch (mux) {
0805 case TM6000_AMUX_SIF1:
0806 case TM6000_AMUX_SIF2:
0807 if (dev->dev_type == TM6010)
0808 tm6010_set_volume_sif(dev, vol);
0809 else
0810 printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has SIF audio inputs. Please check the %s configuration.\n",
0811 dev->name);
0812 break;
0813 case TM6000_AMUX_ADC1:
0814 case TM6000_AMUX_ADC2:
0815 tm6010_set_volume_adc(dev, vol);
0816 break;
0817 default:
0818 break;
0819 }
0820 }
0821
0822 static LIST_HEAD(tm6000_devlist);
0823 static DEFINE_MUTEX(tm6000_devlist_mutex);
0824
0825
0826
0827
0828
0829 void tm6000_remove_from_devlist(struct tm6000_core *dev)
0830 {
0831 mutex_lock(&tm6000_devlist_mutex);
0832 list_del(&dev->devlist);
0833 mutex_unlock(&tm6000_devlist_mutex);
0834 };
0835
0836 void tm6000_add_into_devlist(struct tm6000_core *dev)
0837 {
0838 mutex_lock(&tm6000_devlist_mutex);
0839 list_add_tail(&dev->devlist, &tm6000_devlist);
0840 mutex_unlock(&tm6000_devlist_mutex);
0841 };
0842
0843
0844
0845
0846
0847 static LIST_HEAD(tm6000_extension_devlist);
0848
0849 int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
0850 char *buf, int size)
0851 {
0852 struct tm6000_ops *ops = NULL;
0853
0854
0855
0856 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
0857 if (ops->fillbuf && ops->type == type)
0858 ops->fillbuf(dev, buf, size);
0859 }
0860
0861 return 0;
0862 }
0863
0864 int tm6000_register_extension(struct tm6000_ops *ops)
0865 {
0866 struct tm6000_core *dev = NULL;
0867
0868 mutex_lock(&tm6000_devlist_mutex);
0869 list_add_tail(&ops->next, &tm6000_extension_devlist);
0870 list_for_each_entry(dev, &tm6000_devlist, devlist) {
0871 ops->init(dev);
0872 printk(KERN_INFO "%s: Initialized (%s) extension\n",
0873 dev->name, ops->name);
0874 }
0875 mutex_unlock(&tm6000_devlist_mutex);
0876 return 0;
0877 }
0878 EXPORT_SYMBOL(tm6000_register_extension);
0879
0880 void tm6000_unregister_extension(struct tm6000_ops *ops)
0881 {
0882 struct tm6000_core *dev = NULL;
0883
0884 mutex_lock(&tm6000_devlist_mutex);
0885 list_for_each_entry(dev, &tm6000_devlist, devlist)
0886 ops->fini(dev);
0887
0888 printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
0889 list_del(&ops->next);
0890 mutex_unlock(&tm6000_devlist_mutex);
0891 }
0892 EXPORT_SYMBOL(tm6000_unregister_extension);
0893
0894 void tm6000_init_extension(struct tm6000_core *dev)
0895 {
0896 struct tm6000_ops *ops = NULL;
0897
0898 mutex_lock(&tm6000_devlist_mutex);
0899 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
0900 if (ops->init)
0901 ops->init(dev);
0902 }
0903 mutex_unlock(&tm6000_devlist_mutex);
0904 }
0905
0906 void tm6000_close_extension(struct tm6000_core *dev)
0907 {
0908 struct tm6000_ops *ops = NULL;
0909
0910 mutex_lock(&tm6000_devlist_mutex);
0911 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
0912 if (ops->fini)
0913 ops->fini(dev);
0914 }
0915 mutex_unlock(&tm6000_devlist_mutex);
0916 }