Commit ee6351f5 authored by Ben Collins's avatar Ben Collins Committed by Greg Kroah-Hartman
Browse files

Staging: solo6x10: Support for tw2865 in cascade/full modes



Finally got ahold of a card with a tw2865 video/audio multiplexer and
the spec sheet to go along with it.

Signed-off-by: default avatarBen Collins <bcollins@bluecherry.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 6227157f
Loading
Loading
Loading
Loading
+172 −27
Original line number Diff line number Diff line
@@ -69,6 +69,76 @@ static u8 tbl_tw2864_template[] = {
	0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
};

static u8 tbl_tw2865_ntsc_template[] = {
	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, // 0x00
	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, // 0x10
	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, // 0x20
	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
	0x00, 0xf0, 0x70, 0x48, 0x80, 0x80, 0x00, 0x02, // 0x30
	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
	0x00, 0x00, 0x90, 0x68, 0x00, 0x38, 0x80, 0x80, // 0x40
	0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
	0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, // 0x70
	0xE9, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
	0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, // 0x80
	0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
	0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, // 0x90
	0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
	0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1B, 0x1A, // 0xa0
	0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
	0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, // 0xb0
	0xFF, 0xE7, 0xE9, 0xE9, 0xEB, 0xFF, 0xD6, 0xD8,
	0xD8, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0
	0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
	0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, // 0xd0
	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
	0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, // 0xe0
	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
	0x83, 0xB5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, // 0xf0
	0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
};

static u8 tbl_tw2865_pal_template[] = {
	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, // 0x00
	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, // 0x10
	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, // 0x20
	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, // 0x30
	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
	0x00, 0x94, 0x90, 0x48, 0x00, 0x38, 0x7F, 0x80, // 0x40
	0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
	0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, // 0x70
	0xEA, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
	0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, // 0x80
	0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
	0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, // 0x90
	0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
	0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1A, 0x1A, // 0xa0
	0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
	0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, // 0xb0
	0xFF, 0xE7, 0xE9, 0xE9, 0xE9, 0xFF, 0xD7, 0xD8,
	0xD9, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0
	0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
	0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, // 0xd0
	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
	0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, // 0xe0
	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
	0x83, 0xB5, 0x09, 0x00, 0xA0, 0x00, 0x01, 0x20, // 0xf0
	0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
};

#define is_tw286x(__solo, __id) (!(__solo->tw2815 & (1 << __id)))

static u8 tw_readbyte(struct solo6010_dev *solo_dev, int chip_id, u8 tw6x_off,
@@ -111,18 +181,69 @@ static void tw_write_and_verify(struct solo6010_dev *solo_dev, u8 addr, u8 off,
		msleep_interruptible(1);
	}

	printk("solo6010/tw28: Error writing register: %02x->%02x [%02x]\n",
		addr, off, val);
//	printk("solo6010/tw28: Error writing register: %02x->%02x [%02x]\n",
//		addr, off, val);
}

static int tw2865_setup(struct solo6010_dev *solo_dev, u8 dev_addr)
{
	u8 tbl_tw2865_common[256];
	int i;

	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
		memcpy(tbl_tw2865_common, tbl_tw2865_pal_template,
		       sizeof(tbl_tw2865_common));
	else
		memcpy(tbl_tw2865_common, tbl_tw2865_ntsc_template,
		       sizeof(tbl_tw2865_common));

	/* ALINK Mode */
	if (solo_dev->nr_chans == 4) {
		tbl_tw2865_common[0xd2] = 0x01;
		tbl_tw2865_common[0xcf] = 0x00;
	} else if (solo_dev->nr_chans == 8) {
		tbl_tw2865_common[0xd2] = 0x02;
		if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
			tbl_tw2865_common[0xcf] = 0x80;
	} else if (solo_dev->nr_chans == 16) {
		tbl_tw2865_common[0xd2] = 0x03;
		if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
			tbl_tw2865_common[0xcf] = 0x83;
		else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
			tbl_tw2865_common[0xcf] = 0x83;
		else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
			tbl_tw2865_common[0xcf] = 0x80;
	}

	for (i = 0; i < 0xff; i++) {
		/* Skip read only registers */
		if (i >= 0xb8 && i <= 0xc1 )
			continue;
		if ((i & ~0x30) == 0x00 ||
		    (i & ~0x30) == 0x0c ||
		    (i & ~0x30) == 0x0d)
			continue;
		if (i >= 0xc4 && i <= 0xc7)
			continue;
		if (i == 0xfd)
			continue;

		tw_write_and_verify(solo_dev, dev_addr, i,
				    tbl_tw2865_common[i]);
	}

	return 0;
}

static int tw2864_setup(struct solo6010_dev *solo_dev, u8 dev_addr)
{
	u8 tbl_tw2864_common[256];
	u8 tbl_tw2864_common[sizeof(tbl_tw2864_template)];
	int i;

	memcpy(tbl_tw2864_common, tbl_tw2864_template,
	       sizeof(tbl_tw2864_common));

	if (solo_dev->tw2865 == 0) {
		/* IRQ Mode */
		if (solo_dev->nr_chans == 4) {
			tbl_tw2864_common[0xd2] = 0x01;
@@ -144,6 +265,26 @@ static int tw2864_setup(struct solo6010_dev *solo_dev, u8 dev_addr)
			else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
				tbl_tw2864_common[0xcf] = 0x40;
		}
	} else {
		/* ALINK Mode. Assumes that the first tw28xx is a
		 * 2865 and these are in cascade. */
		for (i = 0; i <= 4; i++)
			tbl_tw2864_common[0x08 | i << 4] = 0x12;

		if (solo_dev->nr_chans == 8) {
			tbl_tw2864_common[0xd2] = 0x02;
			if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
				tbl_tw2864_common[0xcf] = 0x80;
		} else if (solo_dev->nr_chans == 16) {
			tbl_tw2864_common[0xd2] = 0x03;
			if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
				tbl_tw2864_common[0xcf] = 0x83;
			else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
				tbl_tw2864_common[0xcf] = 0x83;
			else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
				tbl_tw2864_common[0xcf] = 0x80;
		}
	}

	/* NTSC or PAL */
	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL) {
@@ -411,8 +552,8 @@ int solo_tw28_init(struct solo6010_dev *solo_dev)

		switch (value >> 3) {
		case 0x18:
			printk("solo6010: 2865 support not enabled\n");
			return -EINVAL;
			solo_dev->tw2865 |= 1 << i;
			solo_dev->tw28_cnt++;
			break;
		case 0x0c:
			solo_dev->tw2864 |= 1 << i;
@@ -434,7 +575,9 @@ int solo_tw28_init(struct solo6010_dev *solo_dev)
	saa7128_setup(solo_dev);

	for (i = 0; i < solo_dev->tw28_cnt; i++) {
		if ((solo_dev->tw2864 & (1 << i)))
		if ((solo_dev->tw2865 & (1 << i)))
			tw2865_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
		else if ((solo_dev->tw2864 & (1 << i)))
			tw2864_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
		else
			tw2815_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
@@ -443,6 +586,8 @@ int solo_tw28_init(struct solo6010_dev *solo_dev)
	dev_info(&solo_dev->pdev->dev, "Initialized %d tw28xx chip%s:",
		 solo_dev->tw28_cnt, solo_dev->tw28_cnt == 1 ? "" : "s");

	if (solo_dev->tw2865)
		printk(" tw2865[%d]", hweight32(solo_dev->tw2865));
	if (solo_dev->tw2864)
		printk(" tw2864[%d]", hweight32(solo_dev->tw2864));
	if (solo_dev->tw2815)
+1 −1
Original line number Diff line number Diff line
@@ -178,7 +178,7 @@ struct solo6010_dev {
	spinlock_t		reg_io_lock;

	/* tw28xx accounting */
	u8			tw2864, tw2815;
	u8			tw2865, tw2864, tw2815;
	u8			tw28_cnt;

	/* i2c related items */