void cx18_halt_firmware(struct cx18 *cx) { CX18_DEBUG_INFO("Preparing for firmware halt.\n"); cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET, 0x0000000F, 0x000F000F); cx18_write_reg_expect(cx, 0x00020002, CX18_ADEC_CONTROL, 0x00000002, 0x00020002); }
/* Selects the audio input and output according to the current settings. */ int cx18_audio_set_io(struct cx18 *cx) { const struct cx18_card_audio_input *in; u32 u, v; int err; /* Determine which input to use */ if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) in = &cx->card->radio_input; else in = &cx->card->audio_inputs[cx->audio_input]; /* handle muxer chips */ v4l2_subdev_call(cx->sd_extmux, audio, s_routing, (u32) in->muxer_input, 0, 0); err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl, audio, s_routing, in->audio_input, 0, 0); if (err) return err; /* FIXME - this internal mux should be abstracted to a subdev */ u = cx18_read_reg(cx, CX18_AUDIO_ENABLE); v = u & ~CX18_AI1_MUX_MASK; switch (in->audio_input) { case CX18_AV_AUDIO_SERIAL1: v |= CX18_AI1_MUX_I2S1; break; case CX18_AV_AUDIO_SERIAL2: v |= CX18_AI1_MUX_I2S2; break; default: v |= CX18_AI1_MUX_843_I2S; break; } if (v == u) { /* force a toggle of some AI1 MUX control bits */ u &= ~CX18_AI1_MUX_MASK; switch (in->audio_input) { case CX18_AV_AUDIO_SERIAL1: u |= CX18_AI1_MUX_843_I2S; break; case CX18_AV_AUDIO_SERIAL2: u |= CX18_AI1_MUX_843_I2S; break; default: u |= CX18_AI1_MUX_I2S1; break; } cx18_write_reg_expect(cx, u | 0xb00, CX18_AUDIO_ENABLE, u, CX18_AI1_MUX_MASK); } cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, v, CX18_AI1_MUX_MASK); return 0; }
static void mb_ack_irq(struct cx18 *cx, struct cx18_epu_work_order *order) { struct cx18_mailbox __iomem *ack_mb; u32 ack_irq, req; switch (order->rpu) { case APU: ack_irq = IRQ_EPU_TO_APU_ACK; ack_mb = &cx->scb->apu2epu_mb; break; case CPU: ack_irq = IRQ_EPU_TO_CPU_ACK; ack_mb = &cx->scb->cpu2epu_mb; break; default: CX18_WARN("Unhandled RPU (%d) for command %x ack\n", order->rpu, order->mb.cmd); return; } req = order->mb.request; /* Don't ack if the RPU has gotten impatient and timed us out */ if (req != cx18_readl(cx, &ack_mb->request) || req == cx18_readl(cx, &ack_mb->ack)) { CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our " "incoming %s to EPU mailbox (sequence no. %u) " "while processing\n", rpu_str[order->rpu], rpu_str[order->rpu], req); order->flags |= CX18_F_EWO_MB_STALE_WHILE_PROC; return; } cx18_writel(cx, req, &ack_mb->ack); cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq); return; }
static void gpio_write(struct cx18 *cx) { u32 dir_lo = cx->gpio_dir & 0xffff; u32 val_lo = cx->gpio_val & 0xffff; u32 dir_hi = cx->gpio_dir >> 16; u32 val_hi = cx->gpio_val >> 16; cx18_write_reg_expect(cx, dir_lo << 16, CX18_REG_GPIO_DIR1, ~dir_lo, dir_lo); cx18_write_reg_expect(cx, (dir_lo << 16) | val_lo, CX18_REG_GPIO_OUT1, val_lo, dir_lo); cx18_write_reg_expect(cx, dir_hi << 16, CX18_REG_GPIO_DIR2, ~dir_hi, dir_hi); cx18_write_reg_expect(cx, (dir_hi << 16) | val_hi, CX18_REG_GPIO_OUT2, val_hi, dir_hi); }
void cx18_init_memory(struct cx18 *cx) { cx18_msleep_timeout(10, 0); cx18_write_reg_expect(cx, 0x00010000, CX18_DDR_SOFT_RESET, 0x00000000, 0x00010001); cx18_msleep_timeout(10, 0); cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG); cx18_msleep_timeout(10, 0); cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH); cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1); cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2); cx18_msleep_timeout(10, 0); /* Initialize DQS pad time */ cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE); cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS); cx18_msleep_timeout(10, 0); cx18_write_reg_expect(cx, 0x00020000, CX18_DDR_SOFT_RESET, 0x00000000, 0x00020002); cx18_msleep_timeout(10, 0); /* use power-down mode when idle */ cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG); cx18_write_reg_expect(cx, 0x00010001, CX18_REG_BUS_TIMEOUT_EN, 0x00000001, 0x00010001); cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7); cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR); cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02); /* AO */ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09); /* AI2 */ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05); /* VIM1 */ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06); /* AI1 */ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07); /* 3D comb */ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10); /* ME */ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12); /* ENC */ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13); /* PK */ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11); /* RC */ cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14); /* AVO */ }
irqreturn_t cx18_irq_handler(int irq, void *dev_id) { struct cx18 *cx = (struct cx18 *)dev_id; u32 sw1, sw2, hw2; sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask; sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & cx->sw2_irq_mask; hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & cx->hw2_irq_mask; if (sw1) cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1); if (sw2) cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2); if (hw2) cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2); if (sw1 || sw2 || hw2) CX18_DEBUG_HI_IRQ("received interrupts " "SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); /* * SW1 responses have to happen first. The sending XPU times out the * incoming mailboxes on us rather rapidly. */ if (sw1) epu_cmd(cx, sw1); /* To do: interrupt-based I2C handling if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) { } */ if (sw2) xpu_ack(cx, sw2); return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE; }
static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) { const struct cx18_api_info *info = find_api_info(cmd); u32 state, irq, req, ack, err; struct cx18_mailbox __iomem *mb; u32 __iomem *xpu_state; wait_queue_head_t *waitq; struct mutex *mb_lock; long int timeout, ret; int i; char argstr[MAX_MB_ARGUMENTS*11+1]; if (info == NULL) { CX18_WARN("unknown cmd %x\n", cmd); return -EINVAL; } if (cx18_debug & CX18_DBGFLG_API) { /* only call u32arr2hex if needed */ if (cmd == CX18_CPU_DE_SET_MDL) { if (cx18_debug & CX18_DBGFLG_HIGHVOL) CX18_DEBUG_HI_API("%s\tcmd %#010x args%s\n", info->name, cmd, u32arr2hex(data, args, argstr)); } else CX18_DEBUG_API("%s\tcmd %#010x args%s\n", info->name, cmd, u32arr2hex(data, args, argstr)); } switch (info->rpu) { case APU: waitq = &cx->mb_apu_waitq; mb_lock = &cx->epu2apu_mb_lock; irq = IRQ_EPU_TO_APU; mb = &cx->scb->epu2apu_mb; xpu_state = &cx->scb->apu_state; break; case CPU: waitq = &cx->mb_cpu_waitq; mb_lock = &cx->epu2cpu_mb_lock; irq = IRQ_EPU_TO_CPU; mb = &cx->scb->epu2cpu_mb; xpu_state = &cx->scb->cpu_state; break; default: CX18_WARN("Unknown RPU (%d) for API call\n", info->rpu); return -EINVAL; } mutex_lock(mb_lock); /* * Wait for an in-use mailbox to complete * * If the XPU is responding with Ack's, the mailbox shouldn't be in * a busy state, since we serialize access to it on our end. * * If the wait for ack after sending a previous command was interrupted * by a signal, we may get here and find a busy mailbox. After waiting, * mark it "not busy" from our end, if the XPU hasn't ack'ed it still. */ state = cx18_readl(cx, xpu_state); req = cx18_readl(cx, &mb->request); timeout = msecs_to_jiffies(10); ret = wait_event_timeout(*waitq, (ack = cx18_readl(cx, &mb->ack)) == req, timeout); if (req != ack) { /* waited long enough, make the mbox "not busy" from our end */ cx18_writel(cx, req, &mb->ack); CX18_ERR("mbox was found stuck busy when setting up for %s; " "clearing busy and trying to proceed\n", info->name); } else if (ret != timeout) CX18_DEBUG_API("waited %u msecs for busy mbox to be acked\n", jiffies_to_msecs(timeout-ret)); /* Build the outgoing mailbox */ req = ((req & 0xfffffffe) == 0xfffffffe) ? 1 : req + 1; cx18_writel(cx, cmd, &mb->cmd); for (i = 0; i < args; i++) cx18_writel(cx, data[i], &mb->args[i]); cx18_writel(cx, 0, &mb->error); cx18_writel(cx, req, &mb->request); cx18_writel(cx, req - 1, &mb->ack); /* ensure ack & req are distinct */ /* * Notify the XPU and wait for it to send an Ack back */ timeout = msecs_to_jiffies((info->flags & API_FAST) ? 10 : 20); CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n", irq, info->name); cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); ret = wait_event_timeout( *waitq, cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request), timeout); if (ret == 0) { /* Timed out */ mutex_unlock(mb_lock); CX18_DEBUG_WARN("sending %s timed out waiting %d msecs for RPU " "acknowledgement\n", info->name, jiffies_to_msecs(timeout)); return -EINVAL; } if (ret != timeout) CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n", jiffies_to_msecs(timeout-ret), info->name); /* Collect data returned by the XPU */ for (i = 0; i < MAX_MB_ARGUMENTS; i++) data[i] = cx18_readl(cx, &mb->args[i]); err = cx18_readl(cx, &mb->error); mutex_unlock(mb_lock); /* * Wait for XPU to perform extra actions for the caller in some cases. * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all buffers * back in a burst shortly thereafter */ if (info->flags & API_SLOW) cx18_msleep_timeout(300, 0); if (err) CX18_DEBUG_API("mailbox error %08x for command %s\n", err, info->name); return err ? -EIO : 0; }
/* All the DVB attach calls go here, this function get's modified * for each new card. cx18_dvb_start_feed() will also need changes. */ static int dvb_register(struct cx18_stream *stream) { struct cx18_dvb *dvb = stream->dvb; struct cx18 *cx = stream->cx; int ret = 0; switch (cx->card->type) { case CX18_CARD_HVR_1600_ESMT: case CX18_CARD_HVR_1600_SAMSUNG: dvb->fe = dvb_attach(s5h1409_attach, &hauppauge_hvr1600_config, &cx->i2c_adap[0]); if (dvb->fe != NULL) { dvb_attach(mxl5005s_attach, dvb->fe, &cx->i2c_adap[0], &hauppauge_hvr1600_tuner); ret = 0; } break; case CX18_CARD_HVR_1600_S5H1411: dvb->fe = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &cx->i2c_adap[0]); if (dvb->fe != NULL) dvb_attach(tda18271_attach, dvb->fe, 0x60, &cx->i2c_adap[0], &hauppauge_tda18271_config); break; case CX18_CARD_LEADTEK_DVR3100H: dvb->fe = dvb_attach(zl10353_attach, &leadtek_dvr3100h_demod, &cx->i2c_adap[1]); if (dvb->fe != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &cx->i2c_adap[1], .i2c_addr = 0xc2 >> 1, .ctrl = NULL, }; static struct xc2028_ctrl ctrl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, .type = XC2028_AUTO, }; fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctrl); } break; case CX18_CARD_YUAN_MPC718: /* * TODO * Apparently, these cards also could instead have a * DiBcom demod supported by one of the db7000 drivers */ dvb->fe = dvb_attach(mt352_attach, &yuan_mpc718_mt352_demod, &cx->i2c_adap[1]); if (dvb->fe == NULL) dvb->fe = dvb_attach(zl10353_attach, &yuan_mpc718_zl10353_demod, &cx->i2c_adap[1]); if (dvb->fe != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &cx->i2c_adap[1], .i2c_addr = 0xc2 >> 1, .ctrl = NULL, }; static struct xc2028_ctrl ctrl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, .type = XC2028_AUTO, }; fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctrl); } break; case CX18_CARD_GOTVIEW_PCI_DVD3: dvb->fe = dvb_attach(zl10353_attach, &gotview_dvd3_zl10353_demod, &cx->i2c_adap[1]); if (dvb->fe != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &cx->i2c_adap[1], .i2c_addr = 0xc2 >> 1, .ctrl = NULL, }; static struct xc2028_ctrl ctrl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, .type = XC2028_AUTO, }; fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctrl); } break; default: /* No Digital Tv Support */ break; } if (dvb->fe == NULL) { CX18_ERR("frontend initialization failed\n"); return -1; } dvb->fe->callback = cx18_reset_tuner_gpio; ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe); if (ret < 0) { if (dvb->fe->ops.release) dvb->fe->ops.release(dvb->fe); return ret; } /* * The firmware seems to enable the TS DMUX clock * under various circumstances. However, since we know we * might use it, let's just turn it on ourselves here. */ cx18_write_reg_expect(cx, (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK, CX18_CLOCK_ENABLE2, CX18_DMUX_CLK_MASK, (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK); return ret; } MODULE_FIRMWARE(FWFILE);
int cx18_firmware_init(struct cx18 *cx) { u32 fw_entry_addr; int sz, retries; u32 api_args[MAX_MB_ARGUMENTS]; /* Allow chip to control CLKRUN */ cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK); /* Stop the firmware */ cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET, 0x0000000F, 0x000F000F); cx18_msleep_timeout(1, 0); /* If the CPU is still running */ if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) { CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__); return -EIO; } cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); sz = load_cpu_fw_direct("v4l-cx23418-cpu.fw", cx->enc_mem, cx); if (sz <= 0) return sz; /* The SCB & IPC area *must* be correct before starting the firmwares */ cx18_init_scb(cx); fw_entry_addr = 0; sz = load_apu_fw_direct("v4l-cx23418-apu.fw", cx->enc_mem, cx, &fw_entry_addr); if (sz <= 0) return sz; /* Start the CPU. The CPU will take care of the APU for us. */ cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET, 0x00000000, 0x00080008); /* Wait up to 500 ms for the APU to come out of reset */ for (retries = 0; retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1; retries++) cx18_msleep_timeout(10, 0); cx18_msleep_timeout(200, 0); if (retries == 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) { CX18_ERR("Could not start the CPU\n"); return -EIO; } /* * The CPU had once before set up to receive an interrupt for it's * outgoing IRQ_CPU_TO_EPU_ACK to us. If it ever does this, we get an * interrupt when it sends us an ack, but by the time we process it, * that flag in the SW2 status register has been cleared by the CPU * firmware. We'll prevent that not so useful condition from happening * by clearing the CPU's interrupt enables for Ack IRQ's we want to * process. */ cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); /* Try a benign command to see if the CPU is alive and well */ sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0); if (sz < 0) return sz; /* initialize GPIO */ cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400); return 0; }
void cx18_init_power(struct cx18 *cx, int lowpwr) { /* power-down Spare and AOM PLLs */ /* power-up fast, slow and mpeg PLLs */ cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN); /* ADEC out of sleep */ cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL, 0x00000000, 0x00020002); /* * The PLL parameters are based on the external crystal frequency that * would ideally be: * * NTSC Color subcarrier freq * 8 = * 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz * * The accidents of history and rationale that explain from where this * combination of magic numbers originate can be found in: * * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80 * * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83 * * As Mike Bradley has rightly pointed out, it's not the exact crystal * frequency that matters, only that all parts of the driver and * firmware are using the same value (close to the ideal value). * * Since I have a strong suspicion that, if the firmware ever assumes a * crystal value at all, it will assume 28.636360 MHz, the crystal * freq used in calculations in this driver will be: * * xtal_freq = 28.636360 MHz * * an error of less than 0.13 ppm which is way, way better than any off * the shelf crystal will have for accuracy anyway. * * Below I aim to run the PLLs' VCOs near 400 MHz to minimze errors. * * Many thanks to Jeff Campbell and Mike Bradley for their extensive * investigation, experimentation, testing, and suggested solutions of * of audio/video sync problems with SVideo and CVBS captures. */ /* the fast clock is at 200/245 MHz */ /* 1 * xtal_freq * 0x0d.f7df9b8 / 2 = 200 MHz: 400 MHz pre post-divide*/ /* 1 * xtal_freq * 0x11.1c71eb8 / 2 = 245 MHz: 490 MHz pre post-divide*/ cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC); cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST); cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE); cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH); /* set slow clock to 125/120 MHz */ /* xtal_freq * 0x0d.1861a20 / 3 = 125 MHz: 375 MHz before post-divide */ /* xtal_freq * 0x0c.92493f8 / 3 = 120 MHz: 360 MHz before post-divide */ cx18_write_reg(cx, lowpwr ? 0xD : 0xC, CX18_SLOW_CLOCK_PLL_INT); cx18_write_reg(cx, lowpwr ? 0x30C344 : 0x124927F, CX18_SLOW_CLOCK_PLL_FRAC); cx18_write_reg(cx, 3, CX18_SLOW_CLOCK_PLL_POST); /* mpeg clock pll 54MHz */ /* xtal_freq * 0xf.15f17f0 / 8 = 54 MHz: 432 MHz before post-divide */ cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT); cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC); cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST); /* Defaults */ /* APU = SC or SC/2 = 125/62.5 */ /* EPU = SC = 125 */ /* DDR = FC = 180 */ /* ENC = SC = 125 */ /* AI1 = SC = 125 */ /* VIM2 = disabled */ /* PCI = FC/2 = 90 */ /* AI2 = disabled */ /* DEMUX = disabled */ /* AO = SC/2 = 62.5 */ /* SER = 54MHz */ /* VFC = disabled */ /* USB = disabled */ if (lowpwr) { cx18_write_reg_expect(cx, 0xFFFF0020, CX18_CLOCK_SELECT1, 0x00000020, 0xFFFFFFFF); cx18_write_reg_expect(cx, 0xFFFF0004, CX18_CLOCK_SELECT2, 0x00000004, 0xFFFFFFFF); } else { /* This doesn't explicitly set every clock select */ cx18_write_reg_expect(cx, 0x00060004, CX18_CLOCK_SELECT1, 0x00000004, 0x00060006); cx18_write_reg_expect(cx, 0x00060006, CX18_CLOCK_SELECT2, 0x00000006, 0x00060006); } cx18_write_reg_expect(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1, 0x00000002, 0xFFFFFFFF); cx18_write_reg_expect(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2, 0x00000104, 0xFFFFFFFF); cx18_write_reg_expect(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1, 0x00009026, 0xFFFFFFFF); cx18_write_reg_expect(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2, 0x00003105, 0xFFFFFFFF); }
int cx18_av_loadfw(struct cx18 *cx) { struct v4l2_subdev *sd = &cx->av_state.sd; const struct firmware *fw = NULL; u32 size; u32 u, v; const u8 *ptr; int i; int retries1 = 0; if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0) { CX18_ERR_DEV(sd, "unable to open firmware %s\n", FWFILE); return -EINVAL; } /* The firmware load often has byte errors, so allow for several retries, both at byte level and at the firmware load level. */ while (retries1 < 5) { cx18_av_write4_expect(cx, CXADEC_CHIP_CTRL, 0x00010000, 0x00008430, 0xffffffff); /* cx25843 */ cx18_av_write_expect(cx, CXADEC_STD_DET_CTL, 0xf6, 0xf6, 0xff); /* Reset the Mako core, Register is alias of CXADEC_CHIP_CTRL */ cx18_av_write4_expect(cx, 0x8100, 0x00010000, 0x00008430, 0xffffffff); /* cx25843 */ /* Put the 8051 in reset and enable firmware upload */ cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000); ptr = fw->data; size = fw->size; for (i = 0; i < size; i++) { u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16); u32 value = 0; int retries2; int unrec_err = 0; for (retries2 = 0; retries2 < CX18_MAX_MMIO_WR_RETRIES; retries2++) { cx18_av_write4_noretry(cx, CXADEC_DL_CTL, dl_control); udelay(10); value = cx18_av_read4(cx, CXADEC_DL_CTL); if (value == dl_control) break; /* Check if we can correct the byte by changing the address. We can only write the lower address byte of the address. */ if ((value & 0x3F00) != (dl_control & 0x3F00)) { unrec_err = 1; break; } } if (unrec_err || retries2 >= CX18_MAX_MMIO_WR_RETRIES) break; } if (i == size) break; retries1++; } if (retries1 >= 5) { CX18_ERR_DEV(sd, "unable to load firmware %s\n", FWFILE); release_firmware(fw); return -EIO; } cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x03000000 | fw->size, 0x03000000, 0x13000000); CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size); if (cx18_av_verifyfw(cx, fw) == 0) cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x13000000 | fw->size, 0x13000000, 0x13000000); /* Output to the 416 */ cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x78000); /* Audio input control 1 set to Sony mode */ /* Audio output input 2 is 0 for slave operation input */ /* 0xC4000914[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */ /* 0xC4000914[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge after WS transition for first bit of audio word. */ cx18_av_write4(cx, CXADEC_I2S_IN_CTL, 0x000000A0); /* Audio output control 1 is set to Sony mode */ /* Audio output control 2 is set to 1 for master mode */ /* 0xC4000918[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */ /* 0xC4000918[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge after WS transition for first bit of audio word. */ /* 0xC4000918[8]: 0 = slave operation, 1 = master (SCK_OUT and WS_OUT are generated) */ cx18_av_write4(cx, CXADEC_I2S_OUT_CTL, 0x000001A0); /* set alt I2s master clock to /0x16 and enable alt divider i2s passthrough */ cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5600B687); cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, 0x000000F6, 0x000000F6, 0x3F00FFFF); /* CxDevWrReg(CXADEC_STD_DET_CTL, 0x000000FF); */ /* Set bit 0 in register 0x9CC to signify that this is MiniMe. */ /* Register 0x09CC is defined by the Merlin firmware, and doesn't have a name in the spec. */ cx18_av_write4(cx, 0x09CC, 1); v = cx18_read_reg(cx, CX18_AUDIO_ENABLE); /* If bit 11 is 1, clear bit 10 */ if (v & 0x800) cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE, 0, 0x400); /* Toggle the AI1 MUX */ v = cx18_read_reg(cx, CX18_AUDIO_ENABLE); u = v & CX18_AI1_MUX_MASK; v &= ~CX18_AI1_MUX_MASK; if (u == CX18_AI1_MUX_843_I2S || u == CX18_AI1_MUX_INVALID) { /* Switch to I2S1 */ v |= CX18_AI1_MUX_I2S1; cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, v, CX18_AI1_MUX_MASK); /* Switch back to the A/V decoder core I2S output */ v = (v & ~CX18_AI1_MUX_MASK) | CX18_AI1_MUX_843_I2S; } else { /* Switch to the A/V decoder core I2S output */ v |= CX18_AI1_MUX_843_I2S; cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, v, CX18_AI1_MUX_MASK); /* Switch back to I2S1 or I2S2 */ v = (v & ~CX18_AI1_MUX_MASK) | u; } cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, v, CX18_AI1_MUX_MASK); /* Enable WW auto audio standard detection */ v = cx18_av_read4(cx, CXADEC_STD_DET_CTL); v |= 0xFF; /* Auto by default */ v |= 0x400; /* Stereo by default */ v |= 0x14000000; cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF); release_firmware(fw); return 0; }
/* init + register i2c algo-bit adapter */ int init_cx18_i2c(struct cx18 *cx) { int i; CX18_DEBUG_I2C("i2c init\n"); /* Sanity checks for the I2C hardware arrays. They must be the * same size and GPIO/CX23418 must be the last entries. */ if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) || ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) || CX18_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 2)) || CX18_HW_CX23418 != (1 << (ARRAY_SIZE(hw_addrs) - 1)) || hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) { CX18_ERR("Mismatched I2C hardware arrays\n"); return -ENODEV; } for (i = 0; i < 2; i++) { memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template, sizeof(struct i2c_adapter)); memcpy(&cx->i2c_algo[i], &cx18_i2c_algo_template, sizeof(struct i2c_algo_bit_data)); cx->i2c_algo_cb_data[i].cx = cx; cx->i2c_algo_cb_data[i].bus_index = i; cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i]; cx->i2c_adap[i].algo_data = &cx->i2c_algo[i]; sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name), " #%d-%d", cx->num, i); i2c_set_adapdata(&cx->i2c_adap[i], cx); memcpy(&cx->i2c_client[i], &cx18_i2c_client_template, sizeof(struct i2c_client)); sprintf(cx->i2c_client[i].name + strlen(cx->i2c_client[i].name), "%d", i); cx->i2c_client[i].adapter = &cx->i2c_adap[i]; cx->i2c_adap[i].dev.parent = &cx->dev->dev; } if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) { /* Reset/Unreset I2C hardware block */ /* Clock select 220MHz */ cx18_write_reg_expect(cx, 0x10000000, 0xc71004, 0x00000000, 0x10001000); /* Clock Enable */ cx18_write_reg_expect(cx, 0x10001000, 0xc71024, 0x00001000, 0x10001000); } /* courtesy of Steven Toth <*****@*****.**> */ cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0); mdelay(10); cx18_write_reg_expect(cx, 0x00c000c0, 0xc7001c, 0x000000c0, 0x00c000c0); mdelay(10); cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0); mdelay(10); /* Set to edge-triggered intrs. */ cx18_write_reg(cx, 0x00c00000, 0xc730c8); /* Clear any stale intrs */ cx18_write_reg_expect(cx, HW2_I2C1_INT|HW2_I2C2_INT, HW2_INT_CLR_STATUS, ~(HW2_I2C1_INT|HW2_I2C2_INT), HW2_I2C1_INT|HW2_I2C2_INT); /* Hw I2C1 Clock Freq ~100kHz */ cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR); cx18_setscl(&cx->i2c_algo_cb_data[0], 1); cx18_setsda(&cx->i2c_algo_cb_data[0], 1); /* Hw I2C2 Clock Freq ~100kHz */ cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR); cx18_setscl(&cx->i2c_algo_cb_data[1], 1); cx18_setsda(&cx->i2c_algo_cb_data[1], 1); cx18_reset_i2c_slaves_gpio(cx); return i2c_bit_add_bus(&cx->i2c_adap[0]) || i2c_bit_add_bus(&cx->i2c_adap[1]); }