示例#1
0
static inline void i2c_set_status(struct saa7134_dev *dev,
				  enum i2c_status status)
{
	d2printk(KERN_DEBUG "%s: i2c stat => %s\n",dev->name,
		 str_i2c_status[status]);
	saa_andorb(SAA7134_I2C_ATTR_STATUS,0x0f,status);
}
示例#2
0
static int tda7432_attach(struct i2c_adapter *adap, int addr,
			  unsigned short flags, int kind)
{
	struct tda7432 *t;
	struct i2c_client *client;
	d2printk("tda7432: In tda7432_attach\n");

	t = kmalloc(sizeof *t,GFP_KERNEL);
	if (!t)
		return -ENOMEM;
	memset(t,0,sizeof *t);

	client = &t->c;
        memcpy(client,&client_template,sizeof(struct i2c_client));
        client->adapter = adap;
        client->addr = addr;
	client->data = t;
	
	do_tda7432_init(client);
	MOD_INC_USE_COUNT;
	strcpy(client->name,"TDA7432");
	printk(KERN_INFO "tda7432: init\n");

	i2c_attach_client(client);
	return 0;
}
示例#3
0
static int tda7432_set(struct i2c_client *client)
{
	struct tda7432 *t = client->data;
	unsigned char buf[16];
	d2printk("tda7432: In tda7432_set\n");
	
	dprintk(KERN_INFO 
		"tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
		t->input,t->volume,t->bass,t->treble,t->lf,t->lr,t->rf,t->rr,t->loud);
	buf[0]  = TDA7432_IN;
	buf[1]  = t->input;
	buf[2]  = t->volume;
	buf[3]  = t->bass;
	buf[4]	= t->treble;
	buf[5]  = t->lf;
	buf[6]  = t->lr;
	buf[7]  = t->rf;
	buf[8]  = t->rr;
	buf[9]  = t->loud;
	if (10 != i2c_master_send(client,buf,10)) {
		printk(KERN_WARNING "tda7432: I/O error, trying tda7432_set\n");
		return -1;
	}

	return 0;
}
示例#4
0
static inline int i2c_send_byte(struct saa7134_dev *dev,
				enum i2c_attr attr,
				unsigned char data)
{
	enum i2c_status status;
	__u32 dword;

	/* have to write both attr + data in one 32bit word */
	dword  = saa_readl(SAA7134_I2C_ATTR_STATUS >> 2);
	dword &= 0x0f;
	dword |= (attr << 6);
	dword |= ((__u32)data << 8);
	dword |= 0x00 << 16;  /* 100 kHz */
//	dword |= 0x40 << 16;  /* 400 kHz */
	dword |= 0xf0 << 24;
	saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword);
	d2printk(KERN_DEBUG "%s: i2c data => 0x%x\n",dev->name,data);

	if (!i2c_is_busy_wait(dev))
		return -EIO;
	status = i2c_get_status(dev);
	if (i2c_is_error(status))
		return -EIO;
	return 0;
}
示例#5
0
static int i2c_reset(struct saa7134_dev *dev)
{
	enum i2c_status status;
	int count;

	d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name);
	status = i2c_get_status(dev);
	if (!i2c_is_error(status))
		return TRUE;
	i2c_set_status(dev,status);

	for (count = 0; count < I2C_WAIT_RETRY; count++) {
		status = i2c_get_status(dev);
		if (!i2c_is_error(status))
			break;
		udelay(I2C_WAIT_DELAY);
	}
	if (I2C_WAIT_RETRY == count)
		return FALSE;

	if (!i2c_is_idle(status))
		return FALSE;

	i2c_set_attr(dev,NOP);
	return TRUE;
}
示例#6
0
static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev)
{
	enum i2c_status status;

	status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f;
	d2printk(KERN_DEBUG "%s: i2c stat <= %s\n",dev->name,
		 str_i2c_status[status]);
	return status;
}
示例#7
0
static int tda7432_read(struct i2c_client *client)
{
	unsigned char buffer;
	d2printk("tda7432: In tda7432_read\n");
	if (1 != i2c_master_recv(client,&buffer,1)) {
		printk(KERN_WARNING "tda7432: I/O error, trying (read)\n");
		return -1;
	}
	dprintk("tda7432: Read 0x%02x\n", buffer); 
	return buffer;
}
示例#8
0
static int tda7432_write(struct i2c_client *client, int subaddr, int val)
{
	unsigned char buffer[2];
	d2printk("tda7432: In tda7432_write\n");
	dprintk("tda7432: Writing %d 0x%x\n", subaddr, val);
	buffer[0] = subaddr;
	buffer[1] = val;
	if (2 != i2c_master_send(client,buffer,2)) {
		printk(KERN_WARNING "tda7432: I/O error, trying (write %d 0x%x)\n",
		       subaddr, val);
		return -1;
	}
	return 0;
}
示例#9
0
static inline int i2c_recv_byte(struct saa7134_dev *dev)
{
	enum i2c_status status;
	unsigned char data;

	i2c_set_attr(dev,CONTINUE);
	if (!i2c_is_busy_wait(dev))
		return -EIO;
	status = i2c_get_status(dev);
	if (i2c_is_error(status))
		return -EIO;
	data = saa_readb(SAA7134_I2C_DATA);
	d2printk(KERN_DEBUG "%s: i2c data <= 0x%x\n",dev->name,data);
	return data;
}
示例#10
0
static void do_tda7432_init(struct i2c_client *client)
{
	struct tda7432 *t = client->data;
	d2printk("tda7432: In tda7432_init\n");

	t->input  = TDA7432_STEREO_IN |  /* Main (stereo) input   */
		    TDA7432_BASS_SYM  |  /* Symmetric bass cut    */
		    TDA7432_BASS_NORM;   /* Normal bass range     */ 
	t->volume =  0x3b ;				 /* -27dB Volume            */
	if (loudness)			 /* Turn loudness on?     */
		t->volume |= TDA7432_LD_ON;	
	t->muted    = VIDEO_AUDIO_MUTE;
	t->treble   = TDA7432_TREBLE_0DB; /* 0dB Treble            */
	t->bass		= TDA7432_BASS_0DB; 	 /* 0dB Bass              */
	t->lf     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
	t->lr     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
	t->rf     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
	t->rr     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
	t->loud   = loudness;		 /* insmod parameter      */

	tda7432_set(client);
}
示例#11
0
static int tda7432_command(struct i2c_client *client,
			   unsigned int cmd, void *arg)
{
	struct tda7432 *t = client->data;
	d2printk("tda7432: In tda7432_command\n");

	switch (cmd) {
	/* --- v4l ioctls --- */
	/* take care: bttv does userspace copying, we'll get a
	   kernel pointer here... */
	
	/* Query card - scale from TDA7432 settings to V4L settings */
	case VIDIOCGAUDIO:
	{
		struct video_audio *va = arg;
		dprintk("tda7432: VIDIOCGAUDIO\n");

		va->flags |= VIDEO_AUDIO_VOLUME |
			VIDEO_AUDIO_BASS |
			VIDEO_AUDIO_TREBLE |
			VIDEO_AUDIO_MUTABLE;
		if (t->muted)
			va->flags |= VIDEO_AUDIO_MUTE;
		va->mode |= VIDEO_SOUND_STEREO;
		/* Master volume control
		 * V4L volume is min 0, max 65535
		 * TDA7432 Volume: 
		 * Min (-79dB) is 0x6f
		 * Max (+20dB) is 0x07 (630)
		 * Max (0dB) is 0x20 (829)
		 * (Mask out bit 7 of vol - it's for the loudness setting)
		 */
		if (!maxvol){  /* max +20db */
			va->volume = ( 0x6f - (t->volume & 0x7F) ) * 630;
		} else {       /* max 0db   */
			va->volume = ( 0x6f - (t->volume & 0x7F) ) * 829;
		}
		
		/* Balance depends on L,R attenuation
		 * V4L balance is 0 to 65535, middle is 32768
		 * TDA7432 attenuation: min (0dB) is 0, max (-37.5dB) is 0x1f
		 * to scale up to V4L numbers, mult by 1057
		 * attenuation exists for lf, lr, rf, rr
		 * we use only lf and rf (front channels)
		 */
		
		if ( (t->lf) < (t->rf) )
			/* right is attenuated, balance shifted left */
			va->balance = (32768 - 1057*(t->rf));
		else
			/* left is attenuated, balance shifted right */
			va->balance = (32768 + 1057*(t->lf));
		
		/* Bass/treble 4 bits each */	
		va->bass=t->bass;
		if(va->bass >= 0x8)
			va->bass = ~(va->bass - 0x8) & 0xf;
		va->bass = (va->bass << 12)+(va->bass << 8)+(va->bass << 4)+(va->bass);
		va->treble=t->treble;
		if(va->treble >= 0x8)
			va->treble = ~(va->treble - 0x8) & 0xf;
		va->treble = (va->treble << 12)+(va->treble << 8)+(va->treble << 4)+(va->treble);
								
		break; /* VIDIOCGAUDIO case */
	}

	/* Set card - scale from V4L settings to TDA7432 settings */
	case VIDIOCSAUDIO:
	{
		struct video_audio *va = arg;
		dprintk("tda7432: VIDEOCSAUDIO\n");

		if(va->flags & VIDEO_AUDIO_VOLUME){
			if(!maxvol){ /* max +20db */
				t->volume = 0x6f - ((va->volume)/630);
			} else {    /* max 0db   */
				t->volume = 0x6f - ((va->volume)/829);
			}
		
		if (loudness)		/* Turn on the loudness bit */
			t->volume |= TDA7432_LD_ON;
		
			tda7432_write(client,TDA7432_VL, t->volume);
		}
		
		if(va->flags & VIDEO_AUDIO_BASS)
		{
			t->bass = va->bass >> 12;
			if(t->bass>= 0x8)
					t->bass = (~t->bass & 0xf) + 0x8 ;
		}
		if(va->flags & VIDEO_AUDIO_TREBLE)
		{
			t->treble= va->treble >> 12;
			if(t->treble>= 0x8)
					t->treble = (~t->treble & 0xf) + 0x8 ;
		}
		if(va->flags & (VIDEO_AUDIO_TREBLE| VIDEO_AUDIO_BASS))
			tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble );
		
		if(va->flags & VIDEO_AUDIO_BALANCE)	{
		if (va->balance < 32768) 
		{
			/* shifted to left, attenuate right */
			t->rr = (32768 - va->balance)/1057;
			t->rf = t->rr;
			t->lr = TDA7432_ATTEN_0DB;
			t->lf = TDA7432_ATTEN_0DB;	
		}
		else if(va->balance > 32769)
		{
			/* shifted to right, attenuate left */
			t->lf = (va->balance - 32768)/1057;
			t->lr = t->lf;
			t->rr = TDA7432_ATTEN_0DB;
			t->rf = TDA7432_ATTEN_0DB;		
		}
		else 
		{
			/* centered */		
			t->rr = TDA7432_ATTEN_0DB;
			t->rf = TDA7432_ATTEN_0DB;
			t->lf = TDA7432_ATTEN_0DB;
			t->lr = TDA7432_ATTEN_0DB;
		}
		}
					
	 	t->muted=(va->flags & VIDEO_AUDIO_MUTE);	
		if (t->muted)
		{
			/* Mute & update balance*/	
			tda7432_write(client,TDA7432_LF, t->lf | TDA7432_MUTE);
			tda7432_write(client,TDA7432_LR, t->lr | TDA7432_MUTE);
			tda7432_write(client,TDA7432_RF, t->rf | TDA7432_MUTE);
			tda7432_write(client,TDA7432_RR, t->rr | TDA7432_MUTE);
		} else {
			tda7432_write(client,TDA7432_LF, t->lf);
			tda7432_write(client,TDA7432_LR, t->lr);
			tda7432_write(client,TDA7432_RF, t->rf);
			tda7432_write(client,TDA7432_RR, t->rr);
		}
							
		break;

	} /* end of VIDEOCSAUDIO case */
示例#12
0
static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
			    struct i2c_msg *msgs, int num)
{
	struct saa7134_dev *dev = i2c_adap->algo_data;
	enum i2c_status status;
	unsigned char data;
	int addr,rc,i,byte;

  	status = i2c_get_status(dev);
	if (!i2c_is_idle(status))
		if (!i2c_reset(dev))
			return -EIO;

	d2printk("start xfer\n");
	d1printk(KERN_DEBUG "%s: i2c xfer:",dev->name);
	for (i = 0; i < num; i++) {
		if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
			/* send address */
			d2printk("send address\n");
			addr  = msgs[i].addr << 1;
			if (msgs[i].flags & I2C_M_RD)
				addr |= 1;
			if (i > 0 && msgs[i].flags & I2C_M_RD) {
				/* workaround for a saa7134 i2c bug
				 * needed to talk to the mt352 demux
				 * thanks to pinnacle for the hint */
				int quirk = 0xfd;
				d1printk(" [%02x quirk]",quirk);
				i2c_send_byte(dev,START,quirk);
				i2c_recv_byte(dev);
			}
			d1printk(" < %02x", addr);
			rc = i2c_send_byte(dev,START,addr);
			if (rc < 0)
				 goto err;
		}
		if (msgs[i].flags & I2C_M_RD) {
			/* read bytes */
			d2printk("read bytes\n");
			for (byte = 0; byte < msgs[i].len; byte++) {
				d1printk(" =");
				rc = i2c_recv_byte(dev);
				if (rc < 0)
					goto err;
				d1printk("%02x", rc);
				msgs[i].buf[byte] = rc;
			}
		} else {
			/* write bytes */
			d2printk("write bytes\n");
			for (byte = 0; byte < msgs[i].len; byte++) {
				data = msgs[i].buf[byte];
				d1printk(" %02x", data);
				rc = i2c_send_byte(dev,CONTINUE,data);
				if (rc < 0)
					goto err;
			}
		}
	}
	d2printk("xfer done\n");
	d1printk(" >");
	i2c_set_attr(dev,STOP);
	rc = -EIO;
	if (!i2c_is_busy_wait(dev))
		goto err;
  	status = i2c_get_status(dev);
	if (i2c_is_error(status))
		goto err;
	/* ensure that the bus is idle for at least one bit slot */
	msleep(1);

	d1printk("\n");
	return num;
 err:
	if (1 == i2c_debug) {
		status = i2c_get_status(dev);
		printk(" ERROR: %s\n",str_i2c_status[status]);
	}
	return rc;
}
示例#13
0
static inline void i2c_set_attr(struct saa7134_dev *dev, enum i2c_attr attr)
{
	d2printk(KERN_DEBUG "%s: i2c attr => %s\n",dev->name,
		 str_i2c_attr[attr]);
	saa_andorb(SAA7134_I2C_ATTR_STATUS,0xc0,attr << 6);
}
static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
			    struct i2c_msg *msgs, int num)
{
	struct saa7134_dev *dev = i2c_adap->algo_data;
	enum i2c_status status;
	unsigned char data;
	int addr,rc,i,byte;

	status = i2c_get_status(dev);
	if (!i2c_is_idle(status))
		if (!i2c_reset(dev))
			return -EIO;

	d2printk("start xfer\n");
	d1printk(KERN_DEBUG "%s: i2c xfer:",dev->name);
	for (i = 0; i < num; i++) {
		if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
			
			d2printk("send address\n");
			addr  = msgs[i].addr << 1;
			if (msgs[i].flags & I2C_M_RD)
				addr |= 1;
			if (i > 0 && msgs[i].flags &
			    I2C_M_RD && msgs[i].addr != 0x40 &&
			    msgs[i].addr != 0x19) {
				int quirk = 0xfe;
				d1printk(" [%02x quirk]",quirk);
				i2c_send_byte(dev,START,quirk);
				i2c_recv_byte(dev);
			}
			d1printk(" < %02x", addr);
			rc = i2c_send_byte(dev,START,addr);
			if (rc < 0)
				 goto err;
		}
		if (msgs[i].flags & I2C_M_RD) {
			
			d2printk("read bytes\n");
			for (byte = 0; byte < msgs[i].len; byte++) {
				d1printk(" =");
				rc = i2c_recv_byte(dev);
				if (rc < 0)
					goto err;
				d1printk("%02x", rc);
				msgs[i].buf[byte] = rc;
			}
			if (0x19 == msgs[i].addr) {
				d1printk(" ?");
				rc = i2c_recv_byte(dev);
				if (rc < 0)
					goto err;
				d1printk("%02x", rc);
			}
		} else {
			
			d2printk("write bytes\n");
			for (byte = 0; byte < msgs[i].len; byte++) {
				data = msgs[i].buf[byte];
				d1printk(" %02x", data);
				rc = i2c_send_byte(dev,CONTINUE,data);
				if (rc < 0)
					goto err;
			}
		}
	}
	d2printk("xfer done\n");
	d1printk(" >");
	i2c_set_attr(dev,STOP);
	rc = -EIO;
	if (!i2c_is_busy_wait(dev))
		goto err;
	status = i2c_get_status(dev);
	if (i2c_is_error(status))
		goto err;
	
	msleep(1);

	d1printk("\n");
	return num;
 err:
	if (1 == i2c_debug) {
		status = i2c_get_status(dev);
		printk(" ERROR: %s\n",str_i2c_status[status]);
	}
	return rc;
}