/*--------------------------------------------------------------------------- * acc_i2c_set_base_address * * This routine sets the base address of the I2C bus *--------------------------------------------------------------------------- */ unsigned short acc_i2c_set_base_address(unsigned char busnum, short adr) { unsigned short ab_base_addr; /* Get Super I/O Index and Data registers */ if (!sio_set_index_data_reg()) return (0); /* Configure LDN to current ACB */ if (busnum == 1) sio_write_reg(LDN, ACB1_LDN); if (busnum == 2) sio_write_reg(LDN, ACB2_LDN); if (adr == -1) { /* Get ACCESS.bus base address */ ab_base_addr = sio_read_reg(BASE_ADR_MSB_REG); ab_base_addr = ab_base_addr << 8; ab_base_addr |= sio_read_reg(BASE_ADR_LSB_REG); if (ab_base_addr != 0) return ab_base_addr; else adr = (busnum == 1 ? ACB1_BASE : ACB2_BASE); } /* Set ACCESS.bus base address */ sio_write_reg(BASE_ADR_LSB_REG, (unsigned char) (adr & 0xFF)); sio_write_reg(BASE_ADR_MSB_REG, (unsigned char) (adr >> 8)); return adr; }
static int fintek_8250_check_id(struct fintek_8250 *pdata) { u16 chip; if (sio_read_reg(pdata, VENDOR_ID1) != VENDOR_ID1_VAL) return -ENODEV; if (sio_read_reg(pdata, VENDOR_ID2) != VENDOR_ID2_VAL) return -ENODEV; chip = sio_read_reg(pdata, CHIP_ID1); chip |= sio_read_reg(pdata, CHIP_ID2) << 8; switch (chip) { case CHIP_ID_F81865: case CHIP_ID_F81866: case CHIP_ID_F81216AD: case CHIP_ID_F81216H: case CHIP_ID_F81216: break; default: return -ENODEV; } pdata->pid = chip; return 0; }
int sio_readw(int index, int addr) { int data; data = sio_read_reg(index, addr) << 8; data |= sio_read_reg(index + 1, addr); return data; }
void vgatv_get_position( unsigned long tv_std, int *p_left, int *p_top, int *p_width, int *p_height) { int k; int vga_pixels; unsigned long ivo; unsigned long hsc_reg; int hsc; unsigned long iho; // tv_std is valid. k = map_tvstd_to_index(tv_std); // vga pixels is vga width, except in 1024x768, where it's half that. vga_pixels = g_specs.vga_hactive; if (1024 == vga_pixels) vga_pixels /= 2; // read ivo and reverse calculate top sio_read_reg(SIO_IVO, &ivo); *p_top = (g_specs.vga_vtotal - g_specs.vga_vsync - (int)ivo) * g_specs.tv_vtotal; // round out if (*p_top < 0) *p_top = (*p_top - g_specs.vga_vtotal + 1) / g_specs.vga_vtotal; else *p_top = (*p_top + g_specs.vga_vtotal - 1) / g_specs.vga_vtotal; // reverse calculate height *p_height = ((2 * g_specs.vga_vactive * tvsetup.tv_lines[k] / g_specs.vga_vtotal) + 1) / 2; // read hsc and extend sign sio_read_reg(SIO_HSC, &hsc_reg); if (hsc_reg & 0xFF) hsc = hsc_reg - 0x100; else hsc = hsc_reg >> 8; // reverse calculate width *p_width = ((2 * (256 + (hsc * 2)) * vga_pixels / 256) + 1) / 2; // read iho and reverse calculate left // account for negative rounding sio_read_reg(SIO_IHO, &iho); *p_left = 2 * ((g_specs.vga_htotal - g_specs.vga_hsync) * vga_pixels / g_specs.vga_hactive - (int)iho) * (256 + (hsc * 2)) / 256; if (*p_left < 0) *p_left = (*p_left - 1) / 2; else *p_left = (*p_left + 1) / 2; }
static int probe_setup_port(struct fintek_8250 *pdata, struct uart_8250_port *uart) { static const u16 addr[] = {0x4e, 0x2e}; static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67}; struct irq_data *irq_data; bool level_mode = false; int i, j, k, min, max; for (i = 0; i < ARRAY_SIZE(addr); i++) { for (j = 0; j < ARRAY_SIZE(keys); j++) { pdata->base_port = addr[i]; pdata->key = keys[j]; if (fintek_8250_enter_key(addr[i], keys[j])) continue; if (fintek_8250_check_id(pdata) || fintek_8250_get_ldn_range(pdata, &min, &max)) { fintek_8250_exit_key(addr[i]); continue; } for (k = min; k < max; k++) { u16 aux; sio_write_reg(pdata, LDN, k); aux = sio_read_reg(pdata, IO_ADDR1); aux |= sio_read_reg(pdata, IO_ADDR2) << 8; if (aux != uart->port.iobase) continue; pdata->index = k; irq_data = irq_get_irq_data(uart->port.irq); if (irq_data) level_mode = irqd_is_level_type(irq_data); fintek_8250_set_irq_mode(pdata, level_mode); fintek_8250_set_max_fifo(pdata); fintek_8250_goto_highspeed(uart, pdata); fintek_8250_exit_key(addr[i]); return 0; } fintek_8250_exit_key(addr[i]); } } return -ENODEV; }
static void sio_write_mask_reg(struct fintek_8250 *pdata, u8 reg, u8 mask, u8 data) { u8 tmp; tmp = (sio_read_reg(pdata, reg) & ~mask) | (mask & data); sio_write_reg(pdata, reg, tmp); }
void vgatv_tvout_mode(unsigned long tvout_mode) { unsigned long cr; sio_read_reg(SIO_CR, &cr); // set requested mode switch (tvout_mode) { case FS460_TVOUT_MODE_CVBS_YC: cr &= ~SIO_CR_OFMT; break; case FS460_TVOUT_MODE_RGB: cr |= SIO_CR_OFMT; break; } sio_write_reg(SIO_CR, cr); }
static void isr(void) { static int last_turnfield = 0; static int last_input_field = 0; int field; unsigned int irqcontrol, move_control; int turnfield; int turnfield_active; // if this is not our interrupt, return immediately blender_read_reg(VP_IRQCONTROL, &irqcontrol); if (!(0x07 & irqcontrol)) return; // get the move control register blender_read_reg(VP_MOVE_CONTROL, &move_control); // if this is an output interrupt... if (VP_IRQCONTROL_IRQO & irqcontrol) { int tbc_vld; int active_lines, total_lines; // the field bit tells what polarity the previous field was, // so invert to get the polarity for this field, // assuming odd follows even follows odd. field = (VP_IRQCONTROL_FIELDO & irqcontrol) ? 0 : 1; // determine if this is about to be a duplicate field because of a change in turnfield state. turnfield = (((1 << 7) & move_control) && ((1 << 3) & move_control)) ? 1 : 0; if ((1 << 2) & move_control) turnfield = !turnfield; if (turnfield != last_turnfield) { // this field will be a turnfield, so invert the field flag to reverse // the assumption above that odd follows even follows odd. // TRACE(("turnfield triggered!\n")) field = !field; last_turnfield = turnfield; } // get display height FS460_get_tv_active_lines(&active_lines); // account for NTSC reported as 484, not 487 if (484 == active_lines) active_lines = 487; active_lines /= 2; // if active lines is 288, total is 312, else 262. if (288 == active_lines) total_lines = 312; else total_lines = 262; // the input sync offset is (active_lines - TBC_VLD field) // because the count starts from trailing edge of input vsync and is // latched at the leading edge of output vsync. sio_read_reg(SIO_TBC_VLD, (unsigned long *)&tbc_vld); input_sync_offset = active_lines - tbc_vld; if (input_sync_offset < 0) input_sync_offset += total_lines; // handle input sync offset seek if (SEEK_OFF != seek_state) { int adj, observed_adj; const S_TIMING_SPECS *p = p_specs(); // to adjust the offset, we need to increase VTOTAL by the amount that the // current sync offset needs to be reduced, translated from tv to vga dimensions. if (SEEK_START == seek_state) { seek_adj = (input_sync_offset - seek_offset) * 2 * p->vga_vtotal / p->tv_vtotal; if (seek_adj < -10) seek_adj += (total_lines * 2 * p->vga_vtotal / p->tv_vtotal); seek_state = SEEK_RUNNING; } TRACE(("seek_adj = %d", seek_adj)) observed_adj = (input_sync_offset - seek_offset) * 2 * p->vga_vtotal / p->tv_vtotal; if (observed_adj < -10) observed_adj += (total_lines * 2 * p->vga_vtotal / p->tv_vtotal); TRACE((", observed_adj = %d", observed_adj)) if (0 == seek_adj) { seek_state = SEEK_OFF; TRACE((", stopping")) PL_adjust_vtotal(p->vga_vtotal); } else { adj = seek_adj; if (adj > MAX_ADJ) adj = MAX_ADJ; PL_adjust_vtotal(p->vga_vtotal + adj); TRACE((", adjusting vtotal to %d", p->vga_vtotal + adj)) seek_adj -= adj; } TRACE((".\n")) }
void vgatv_nco(unsigned long tv_std, unsigned long vga_mode, int use_nco) { unsigned long cr, misc; int m, n; unsigned long ncon, ncod; int k; k = map_tvstd_to_index(tv_std); // initialize m, n to make compiler happy m = 512; n = 128; // if M/N mode is selected, make sure it's attainable if (!use_nco) { if ((g_specs.vga_htotal <= 0) || (g_specs.vga_vtotal <= 0)) use_nco = 1; else { m = g_specs.vga_vtotal; if ((m < 500) || (m > 1200)) use_nco = 1; n = g_specs.tv_htotal * g_specs.tv_vtotal / g_specs.vga_htotal; if (g_specs.tv_htotal * g_specs.tv_vtotal != (n * g_specs.vga_htotal)) use_nco = 1; } } // read and store CR. sio_read_reg(SIO_CR, &cr); // make sure NCO_EN (enable latch) bit is clear cr &= ~SIO_CR_NCO_EN; sio_write_reg(SIO_CR, cr); // clear NCO_LOADX. sio_read_reg(SIO_MISC, &misc); misc &= ~(SIO_MISC_NCO_LOAD1 + SIO_MISC_NCO_LOAD0); sio_write_reg(SIO_MISC, misc); if (use_nco) { if (FS460_VGA_MODE_1024X768 == vga_mode) { // setup for M and N load (Nco_load=1). misc |= (SIO_MISC_NCO_LOAD0); sio_write_reg(SIO_MISC, misc); // M and N. sio_write_reg(SIO_NCONL, 1024-2); sio_write_reg(SIO_NCODL, 128-1); // latch M/N in. cr |= SIO_CR_NCO_EN; sio_write_reg(SIO_CR, cr); cr &= ~SIO_CR_NCO_EN; sio_write_reg(SIO_CR, cr); // setup ncon and ncod load (Nco_load=0). misc &= ~(SIO_MISC_NCO_LOAD1 + SIO_MISC_NCO_LOAD0); sio_write_reg(SIO_MISC, misc); // NCON ncon = (unsigned long)g_specs.vga_vtotal * g_specs.vga_htotal / 2; sio_write_reg(SIO_NCONH, ncon >> 16); sio_write_reg(SIO_NCONL, ncon & 0xffff); // NCOD ncod = (unsigned long)g_specs.tv_vtotal * g_specs.vga_htotal * 4; sio_write_reg(SIO_NCODH, ncod >> 16); sio_write_reg(SIO_NCODL, ncod & 0xffff); } else {
void vgatv_tv_std(unsigned long tv_std, unsigned int cp_trigger_bits) { int k; unsigned short reg34; unsigned long cr, w; unsigned long l; // verify supported standard. k = map_tvstd_to_index(tv_std); if (k < 0) return; // store tv width and lines g_specs.tv_htotal = tvsetup.tv_width[k]; g_specs.tv_vtotal = tvsetup.tv_lines[k]; // set PAL or NTSC in CR register sio_read_reg(SIO_CR, &cr); cr &= ~SIO_CR_656_PAL_NTSC; cr |= tvsetup.cr[k]; sio_write_reg(SIO_CR, cr); // setup the encoder. l = tvsetup.chroma_freq[k]; enc_write_reg(ENC_CHROMA_FREQ, (int)(l & 0x00ff)); enc_write_reg(ENC_CHROMA_FREQ+1, (int)((l>>8) & 0x00ff)); enc_write_reg(ENC_CHROMA_FREQ+2, (int)((l>>16) & 0x00ff)); enc_write_reg(ENC_CHROMA_FREQ+3, (int)((l>>24) & 0x00ff)); enc_write_reg(ENC_CHROMA_PHASE, tvsetup.chroma_phase[k]); enc_write_reg(ENC_REG05, 0x00); // reg 0x05 enc_write_reg(ENC_REG06, 0x89); // reg 0x06 enc_write_reg(ENC_REG07, 0x00); // reg 0x07 enc_write_reg(ENC_HSYNCWIDTH, tvsetup.hsync_width[k]); enc_write_reg(ENC_BURSTWIDTH, tvsetup.burst_width[k]); enc_write_reg(ENC_BACKPORCH, tvsetup.back_porch[k]); enc_write_reg(ENC_CB_BURSTLEVEL, tvsetup.cb_burst_level[k]); enc_write_reg(ENC_CR_BURSTLEVEL, tvsetup.cr_burst_level[k]); enc_write_reg(ENC_SLAVEMODE, 0x01); // slave mode if (cp_trigger_bits == 0) w = w10bit2z(tvsetup.blank_level[k]); else w = w10bit2z((unsigned short)(tvsetup.blank_level[k]-tvsetup.hamp_offset[k])); enc_write_reg(ENC_BLANKLEVEL, w & 0x00ff); enc_write_reg(ENC_BLANKLEVEL+1, w >> 8); enc_write_reg(ENC_TINT, 0x00); // tint enc_write_reg(ENC_BREEZEWAY, tvsetup.breeze_way[k]); enc_write_reg(ENC_FRONTPORCH, tvsetup.front_porch[k]); enc_write_reg(ENC_FIRSTVIDEOLINE, tvsetup.firstline[k]); // firstvideoline reg34 = (tvsetup.pal_mode[k] << 6) | (tvsetup.sys625_50[k] << 4) | (tvsetup.sys625_50[k] << 3) | (tvsetup.cphase_rst[k] << 1) | (tvsetup.vsync5[k]); enc_write_reg(ENC_REG34, reg34); // reg 0x34 enc_write_reg(ENC_SYNCLEVEL, tvsetup.sync_level[k]); if (cp_trigger_bits == 0) w = w10bit2z(tvsetup.vbi_blank_level[k]); else w = w10bit2z((unsigned short)(tvsetup.vbi_blank_level[k]-1)); enc_write_reg(ENC_VBI_BLANKLEVEL, w & 0x00ff); enc_write_reg(ENC_VBI_BLANKLEVEL+1, w >> 8); }
void vgatv_vga_mode(unsigned long vga_mode, unsigned long tv_std, int htotal, int vtotal) { static struct { unsigned long mode; int width; int lines; } vgaparams[] = { {FS460_VGA_MODE_640X480, 640, 480}, {FS460_VGA_MODE_720X487, 720, 480}, {FS460_VGA_MODE_720X576, 720, 576}, {FS460_VGA_MODE_800X600, 800, 600}, {FS460_VGA_MODE_1024X768, 1024, 768}, }; unsigned long cr, misc, byp; unsigned int i; g_specs.vga_hactive = 0; g_specs.vga_vactive = 0; g_specs.vga_htotal = 0; g_specs.vga_hdiv = 1; for (i = 0; i < sizeof(vgaparams) / sizeof(*vgaparams); i++) { if (vga_mode == vgaparams[i].mode) { g_specs.vga_hactive = vgaparams[i].width; g_specs.vga_vactive = vgaparams[i].lines; get_vga_htotal(vga_mode, tv_std); // override if specified if (htotal) g_specs.vga_htotal = htotal; g_specs.vga_vtotal_specified = vtotal; if (vtotal) g_specs.vga_vtotal = vtotal; // set divisor for div2 mode switch(vga_mode) { case FS460_VGA_MODE_1024X768: g_specs.vga_hdiv = 2; break; } break; } } if (!g_specs.vga_hactive) return; // clock mux decimator and vga dual. sio_read_reg(SIO_CR, &cr); sio_read_reg(SIO_MISC, &misc); sio_read_reg(SIO_BYP, &byp); if (vga_mode == FS460_VGA_MODE_1024X768) { // XGA cr |= SIO_CR_UIM_DEC; misc |= SIO_MISC_VGACKDIV; byp |= (SIO_BYP_HDS | SIO_BYP_CAC); } else { // VGA,SVGA cr &= ~SIO_CR_UIM_DEC; misc &= ~SIO_MISC_VGACKDIV; byp &= ~(SIO_BYP_HDS | SIO_BYP_CAC); } sio_write_reg(SIO_CR, cr); sio_write_reg(SIO_MISC, misc); sio_write_reg(SIO_BYP, byp); }