static int default_polling_getkey(struct tm6000_IR *ir, struct tm6000_ir_poll_result *poll_result) { struct tm6000_core *dev = ir->dev; int rc; u8 buf[2]; if (ir->wait && !&dev->int_in) return 0; if (&dev->int_in) { if (ir->ir.ir_type == IR_TYPE_RC5) poll_result->rc_data = ir->urb_data[0]; else poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8; } else { tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); msleep(10); tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); msleep(10); if (ir->ir.ir_type == IR_TYPE_RC5) { rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, REQ_02_GET_IR_CODE, 0, 0, buf, 1); msleep(10); dprintk("read data=%02x\n", buf[0]); if (rc < 0) return rc; poll_result->rc_data = buf[0]; } else { rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, REQ_02_GET_IR_CODE, 0, 0, buf, 2); msleep(10); dprintk("read data=%04x\n", buf[0] | buf[1] << 8); if (rc < 0) return rc; poll_result->rc_data = buf[0] | buf[1] << 8; } if ((poll_result->rc_data & 0x00ff) != 0xff) ir->key = 1; } return 0; }
/* * BOARD Specific: Resets audio DMA */ static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip) { struct tm6000_core *core = chip->core; int val; dprintk(1, "Stopping audio DMA\n"); /* Enables audio */ val = tm6000_get_reg(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0x0); val &= ~0x20; tm6000_set_reg(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val); tm6000_set_reg(core, TM6010_REQ08_R01_A_INIT, 0); return 0; }
static void tm6000_ir_int_work(struct work_struct *work) { struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); struct tm6000_core *dev = ir->dev; int rc; dprintk(3, "%s, submit_urb = %d, pwled = %d\n",__func__, ir->submit_urb, ir->pwled); if (ir->submit_urb) { dprintk(3, "Resubmit urb\n"); tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); rc = usb_submit_urb(ir->int_urb, GFP_ATOMIC); if (rc < 0) { printk(KERN_ERR "tm6000: Can't submit an IR interrupt. Error %i\n", rc); /* Retry in 100 ms */ schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY)); return; } ir->submit_urb = 0; } /* Led is enabled only if USB submit doesn't fail */ if (ir->pwled == 2) { tm6000_flash_led(dev, 0); ir->pwled = 0; schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_INT_LED_DELAY)); } else if (!ir->pwled) { tm6000_flash_led(dev, 1); ir->pwled = 1; } }
/* * BOARD Specific: Resets audio DMA */ static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip) { struct tm6000_core *core = chip->core; dprintk(1, "Stopping audio DMA\n"); /* Disables audio */ tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0x00, 0x40); tm6000_set_reg(core, TM6010_REQ08_R01_A_INIT, 0); return 0; }
static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip) { struct tm6000_core *core = chip->core; dprintk(1, "Starting audio DMA\n"); /* Enables audio */ tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0x40, 0x40); tm6000_set_audio_bitrate(core, 48000); tm6000_set_reg(core, TM6010_REQ08_R01_A_INIT, 0x80); return 0; }
static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) { struct tm6000_core *dev = i2c_adap->algo_data; int addr, rc, i, byte; if (num <= 0) return 0; for (i = 0; i < num; i++) { addr = (msgs[i].addr << 1) & 0xff; i2c_dprintk(2, "%s %s addr=0x%x len=%d:", (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); if (msgs[i].flags & I2C_M_RD) { /* read request without preceding register selection */ /* * The TM6000 only supports a read transaction * immediately after a 1 or 2 byte write to select * a register. We cannot fulfil this request. */ i2c_dprintk(2, " read without preceding write not" " supported"); rc = -EOPNOTSUPP; goto err; } else if (i + 1 < num && msgs[i].len <= 2 && (msgs[i + 1].flags & I2C_M_RD) && msgs[i].addr == msgs[i + 1].addr) { /* 1 or 2 byte write followed by a read */ if (i2c_debug >= 2) for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); i2c_dprintk(2, "; joined to read %s len=%d:", i == num - 2 ? "stop" : "nonstop", msgs[i + 1].len); if (msgs[i].len == 2) { rc = tm6000_i2c_recv_regs16(dev, addr, msgs[i].buf[0] << 8 | msgs[i].buf[1], msgs[i + 1].buf, msgs[i + 1].len); } else { rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0], msgs[i + 1].buf, msgs[i + 1].len); } i++; if (addr == dev->tuner_addr << 1) { tm6000_set_reg(dev, REQ_50_SET_START, 0, 0); tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0); } if (i2c_debug >= 2) for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); } else { /* write bytes */ if (i2c_debug >= 2) for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0], msgs[i].buf + 1, msgs[i].len - 1); if (addr == dev->tuner_addr << 1) { tm6000_set_reg(dev, REQ_50_SET_START, 0, 0); tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0); } } if (i2c_debug >= 2) printk("\n"); if (rc < 0) goto err; } return num; err: i2c_dprintk(2, " ERROR: %i\n", rc); return rc; }
static int tm6000_ir_config(struct tm6000_IR *ir) { struct tm6000_core *dev = ir->dev; u32 pulse = 0, leader = 0; dprintk(2, "%s\n",__func__); /* * The IR decoder supports RC-5 or NEC, with a configurable timing. * The timing configuration there is not that accurate, as it uses * approximate values. The NEC spec mentions a 562.5 unit period, * and RC-5 uses a 888.8 period. * Currently, driver assumes a clock provided by a 12 MHz XTAL, but * a modprobe parameter can adjust it. * Adjustments are required for other timings. * It seems that the 900ms timing for NEC is used to detect a RC-5 * IR, in order to discard such decoding */ switch (ir->rc_type) { case RC_BIT_NEC: leader = 900; /* ms */ pulse = 700; /* ms - the actual value would be 562 */ break; default: case RC_BIT_RC5: leader = 900; /* ms - from the NEC decoding */ pulse = 1780; /* ms - The actual value would be 1776 */ break; } pulse = ir_clock_mhz * pulse; leader = ir_clock_mhz * leader; if (ir->rc_type == RC_BIT_NEC) leader = leader | 0x8000; dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n", __func__, (ir->rc_type == RC_BIT_NEC) ? "NEC" : "RC-5", ir_clock_mhz, leader, pulse); /* Remote WAKEUP = enable, normal mode, from IR decoder output */ tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe); /* Enable IR reception on non-busrt mode */ tm6000_set_reg(dev, TM6010_REQ07_RD8_IR, 0x2f); /* IR_WKUP_SEL = Low byte in decoded IR data */ tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff); /* IR_WKU_ADD code */ tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff); tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, leader >> 8); tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, leader); tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, pulse >> 8); tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, pulse); if (!ir->polling) tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); else tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); msleep(10); /* Shows that IR is working via the LED */ tm6000_flash_led(dev, 0); msleep(100); tm6000_flash_led(dev, 1); ir->pwled = 1; return 0; }