/*---------------------------------------------------------------------------
 * 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;
}
예제 #2
0
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;
}
예제 #3
0
파일: scan_sio.c 프로젝트: planykao/sio_pch
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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);
}
예제 #7
0
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);
}
예제 #8
0
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"))
		}
예제 #9
0
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
		{
예제 #10
0
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);
}
예제 #11
0
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);
}