Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61391e04 authored by Tim Kaiser's avatar Tim Kaiser Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (4219): Av7110: analog sound output of DVB-C rev 2.3



Added support for the msp34x5 audio dac. Analog sound output of
Technotrend DVB-C 2300 (aka Hauppauge Nexus-CA) works now.

Signed-off-by: default avatarTim Kaiser <timkaiser@t-online.de>
Signed-off-by: default avatarMarco Schluessler <marco@lordzodiac.de>
Signed-off-by: default avatarOliver Endriss <o.endriss@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 4a4edcca
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -152,13 +152,9 @@ static void init_av7110_av(struct av7110 *av7110)
	/* remaining inits according to card and frontend type */
	av7110->analog_tuner_flags = 0;
	av7110->current_input = 0;
	if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) {
		printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n",
			av7110->dvb_adapter.num);
		av7110->adac_type = DVB_ADAC_MSP34x5;
	if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
		av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
	}
	else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
	if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
		printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
			av7110->dvb_adapter.num);
		av7110->adac_type = DVB_ADAC_CRYSTAL;
+22 −3
Original line number Diff line number Diff line
@@ -318,7 +318,17 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
		msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */
		msp_writereg(av7110, MSP_WR_DSP, 0x0006, val); /* headphonesr */
		return 0;

	case DVB_ADAC_MSP34x5:
		vol = (volleft > volright) ? volleft : volright;
		val = (vol * 0x73 / 255) << 8;
		if (vol > 0)
			balance = ((volright - volleft) * 127) / vol;
		msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8);
		msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */
		return 0;
	}

	return 0;
}

@@ -1267,23 +1277,32 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
		switch(av7110->audiostate.channel_select) {
		case AUDIO_STEREO:
			ret = audcom(av7110, AUDIO_CMD_STEREO);
			if (!ret)
			if (!ret) {
				if (av7110->adac_type == DVB_ADAC_CRYSTAL)
					i2c_writereg(av7110, 0x20, 0x02, 0x49);
				else if (av7110->adac_type == DVB_ADAC_MSP34x5)
					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220);
			}
			break;

		case AUDIO_MONO_LEFT:
			ret = audcom(av7110, AUDIO_CMD_MONO_L);
			if (!ret)
			if (!ret) {
				if (av7110->adac_type == DVB_ADAC_CRYSTAL)
					i2c_writereg(av7110, 0x20, 0x02, 0x4a);
				else if (av7110->adac_type == DVB_ADAC_MSP34x5)
					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0200);
			}
			break;

		case AUDIO_MONO_RIGHT:
			ret = audcom(av7110, AUDIO_CMD_MONO_R);
			if (!ret)
			if (!ret) {
				if (av7110->adac_type == DVB_ADAC_CRYSTAL)
					i2c_writereg(av7110, 0x20, 0x02, 0x45);
				else if (av7110->adac_type == DVB_ADAC_MSP34x5)
					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0210);
			}
			break;

		default:
+40 −10
Original line number Diff line number Diff line
@@ -42,7 +42,18 @@
int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val)
{
	u8 msg[5] = { dev, reg >> 8, reg & 0xff, val >> 8 , val & 0xff };
	struct i2c_msg msgs = { .flags = 0, .addr = 0x40, .len = 5, .buf = msg };
	struct i2c_msg msgs = { .flags = 0, .len = 5, .buf = msg };

	switch (av7110->adac_type) {
	case DVB_ADAC_MSP34x0:
		msgs.addr = 0x40;
		break;
	case DVB_ADAC_MSP34x5:
		msgs.addr = 0x42;
		break;
	default:
		return 0;
	}

	if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) {
		dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n",
@@ -57,10 +68,23 @@ static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
	u8 msg1[3] = { dev, reg >> 8, reg & 0xff };
	u8 msg2[2];
	struct i2c_msg msgs[2] = {
		{ .flags = 0,	     .addr = 0x40, .len = 3, .buf = msg1 },
		{ .flags = I2C_M_RD, .addr = 0x40, .len = 2, .buf = msg2 }
		{ .flags = 0	   , .len = 3, .buf = msg1 },
		{ .flags = I2C_M_RD, .len = 2, .buf = msg2 }
	};

	switch (av7110->adac_type) {
	case DVB_ADAC_MSP34x0:
		msgs[0].addr = 0x40;
		msgs[1].addr = 0x40;
		break;
	case DVB_ADAC_MSP34x5:
		msgs[0].addr = 0x42;
		msgs[1].addr = 0x42;
		break;
	default:
		return 0;
	}

	if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) {
		dprintk(1, "dvb-ttpci: failed @ card %d, %u\n",
		       av7110->dvb_adapter.num, reg);
@@ -678,17 +702,23 @@ int av7110_init_analog_module(struct av7110 *av7110)
{
	u16 version1, version2;

	if (i2c_writereg(av7110, 0x80, 0x0, 0x80) != 1
	    || i2c_writereg(av7110, 0x80, 0x0, 0) != 1)
		return -ENODEV;

	if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
	    i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
		printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
			av7110->dvb_adapter.num);
		av7110->adac_type = DVB_ADAC_MSP34x0;
	} else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
		   i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
		printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n",
			av7110->dvb_adapter.num);
		av7110->adac_type = DVB_ADAC_MSP34x5;
	} else
		return -ENODEV;

	msleep(100); // the probing above resets the msp...
	msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
	msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
	dprintk(1, "dvb-ttpci: @ card %d MSP3400 version 0x%04x 0x%04x\n",
	dprintk(1, "dvb-ttpci: @ card %d MSP34xx version 0x%04x 0x%04x\n",
		av7110->dvb_adapter.num, version1, version2);
	msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
	msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
@@ -697,7 +727,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
	msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume
	msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
	msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
	msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x4800); // prescale SCART
	msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART

	if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
		INFO(("saa7113 not accessible.\n"));