92 lines
		
	
	
	
		
			1.8 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			92 lines
		
	
	
	
		
			1.8 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * L3 code | ||
|  |  * | ||
|  |  *  Copyright (C) 2008, Christian Pellegrin <chripell@evolware.org> | ||
|  |  * | ||
|  |  * This program is free software; you can redistribute it and/or modify | ||
|  |  * it under the terms of the GNU General Public License version 2 as | ||
|  |  * published by the Free Software Foundation. | ||
|  |  * | ||
|  |  * | ||
|  |  * based on: | ||
|  |  * | ||
|  |  * L3 bus algorithm module. | ||
|  |  * | ||
|  |  *  Copyright (C) 2001 Russell King, All Rights Reserved. | ||
|  |  * | ||
|  |  * | ||
|  |  */ | ||
|  | 
 | ||
|  | #include <linux/module.h>
 | ||
|  | #include <linux/kernel.h>
 | ||
|  | #include <linux/delay.h>
 | ||
|  | 
 | ||
|  | #include <sound/l3.h>
 | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Send one byte of data to the chip.  Data is latched into the chip on | ||
|  |  * the rising edge of the clock. | ||
|  |  */ | ||
|  | static void sendbyte(struct l3_pins *adap, unsigned int byte) | ||
|  | { | ||
|  | 	int i; | ||
|  | 
 | ||
|  | 	for (i = 0; i < 8; i++) { | ||
|  | 		adap->setclk(0); | ||
|  | 		udelay(adap->data_hold); | ||
|  | 		adap->setdat(byte & 1); | ||
|  | 		udelay(adap->data_setup); | ||
|  | 		adap->setclk(1); | ||
|  | 		udelay(adap->clock_high); | ||
|  | 		byte >>= 1; | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Send a set of bytes to the chip.  We need to pulse the MODE line | ||
|  |  * between each byte, but never at the start nor at the end of the | ||
|  |  * transfer. | ||
|  |  */ | ||
|  | static void sendbytes(struct l3_pins *adap, const u8 *buf, | ||
|  | 		      int len) | ||
|  | { | ||
|  | 	int i; | ||
|  | 
 | ||
|  | 	for (i = 0; i < len; i++) { | ||
|  | 		if (i) { | ||
|  | 			udelay(adap->mode_hold); | ||
|  | 			adap->setmode(0); | ||
|  | 			udelay(adap->mode); | ||
|  | 		} | ||
|  | 		adap->setmode(1); | ||
|  | 		udelay(adap->mode_setup); | ||
|  | 		sendbyte(adap, buf[i]); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len) | ||
|  | { | ||
|  | 	adap->setclk(1); | ||
|  | 	adap->setdat(1); | ||
|  | 	adap->setmode(1); | ||
|  | 	udelay(adap->mode); | ||
|  | 
 | ||
|  | 	adap->setmode(0); | ||
|  | 	udelay(adap->mode_setup); | ||
|  | 	sendbyte(adap, addr); | ||
|  | 	udelay(adap->mode_hold); | ||
|  | 
 | ||
|  | 	sendbytes(adap, data, len); | ||
|  | 
 | ||
|  | 	adap->setclk(1); | ||
|  | 	adap->setdat(1); | ||
|  | 	adap->setmode(0); | ||
|  | 
 | ||
|  | 	return len; | ||
|  | } | ||
|  | EXPORT_SYMBOL_GPL(l3_write); | ||
|  | 
 | ||
|  | MODULE_DESCRIPTION("L3 bit-banging driver"); | ||
|  | MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>"); | ||
|  | MODULE_LICENSE("GPL"); |