tas3001c.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Driver for the i2c/i2s based TA3001C sound chip used
  3.  * on some Apple hardware. Also known as "tumbler".
  4.  *
  5.  *  This file is subject to the terms and conditions of the GNU General Public
  6.  *  License.  See the file COPYING in the main directory of this archive
  7.  *  for more details.
  8.  *
  9.  * Modified by Christopher C. Chimelis <chris@debian.org>:
  10.  *
  11.  *   TODO:
  12.  *   -----
  13.  *   * Enable DRC since the TiBook speakers are less than good
  14.  *   * Enable control over input line 2 (is this connected?)
  15.  *   * Play with the dual six-stage cascading biquad filtering to see how
  16.  *     we can use it to our advantage (currently not implemented)
  17.  *   * Reorganise driver a bit to make it cleaner and easier to work with
  18.  *     (read: use the header file more :-P)
  19.  *   * Implement sleep support
  20.  *
  21.  *   Version 0.4:
  22.  *   ------------
  23.  *   * Balance control finally works (can someone document OSS better please?)
  24.  *   * Moved to a struct for common values referenced in the driver
  25.  *   * Put stubs in for sleep/wake-up support for now.  This will take some
  26.  *     experimentation to make sure that the timing is right, since the
  27.  *     TAS hardware requires specific timing while enabling low-power mode.
  28.  *     I may cheat for now and just reset the chip on wake-up, but I'd rather
  29.  *     not if I don't have to.
  30.  *
  31.  *   Version 0.3:
  32.  *   ------------
  33.  *   * Fixed volume control
  34.  *   * Added bass and treble control
  35.  *   * Added PCM line level control (mixer 1 in the TAS manual)
  36.  *
  37.  */
  38. #include <linux/version.h>
  39. #include <linux/module.h>
  40. #include <linux/slab.h>
  41. #include <linux/proc_fs.h>
  42. #include <linux/ioport.h>
  43. #include <linux/sysctl.h>
  44. #include <linux/types.h>
  45. #include <linux/i2c.h>
  46. #include <linux/init.h>
  47. #include <asm/uaccess.h>
  48. #include <asm/errno.h>
  49. #include <asm/io.h>
  50. #include <asm/prom.h>
  51. #include "dmasound.h"
  52. #include "tas3001c.h"
  53. #define I2C_DRIVERID_TAS (0xFEBA)
  54. #define TAS_VERSION "0.3"
  55. #define TAS_DATE "20011214"
  56. #define TAS_SETTING_MAX 100
  57. #define VOL_DEFAULT (((((TAS_SETTING_MAX*4)/5)<<0)<<8) | (((TAS_SETTING_MAX*4)/5)<<0))
  58. #define INPUT_DEFAULT (((TAS_SETTING_MAX*4)/5)<<0)
  59. #define BASS_DEFAULT ((TAS_SETTING_MAX/2)<<0)
  60. #define TREBLE_DEFAULT ((TAS_SETTING_MAX/2)<<0)
  61. static struct i2c_client * tumbler_client = NULL;
  62. int tumbler_enter_sleep(void);
  63. int tumbler_leave_sleep(void);
  64. static int tas_attach_adapter(struct i2c_adapter *adapter);
  65. static int tas_detect_client(struct i2c_adapter *adapter, int address);
  66. static int tas_detach_client(struct i2c_client *client);
  67. /* Unique ID allocation */
  68. static int tas_id;
  69. static int tas_initialized;
  70. static struct device_node* tas_node;
  71. static u8 tas_i2c_address = 0x34;
  72. struct tas_data_t {
  73. uint left_vol; /* left volume */
  74. uint right_vol; /* right volume */
  75. uint treble; /* treble */
  76. uint bass; /* bass */
  77. uint pcm_level; /* pcm level */
  78. };
  79. struct i2c_driver tas_driver = {  
  80. name: "TAS3001C driver  V 0.3",
  81. id: I2C_DRIVERID_TAS,
  82. flags: I2C_DF_NOTIFY,
  83. attach_adapter: &tas_attach_adapter,
  84. detach_client: &tas_detach_client,
  85. command: NULL,
  86. inc_use: NULL, /* &tas_inc_use, */
  87. dec_use: NULL  /* &tas_dev_use  */
  88. };
  89. int
  90. tumbler_get_volume(uint * left_vol, uint  *right_vol)
  91. {
  92. struct tas_data_t *data;
  93. if (!tumbler_client)
  94. return -1;
  95. data = (struct tas_data_t *) (tumbler_client->data);
  96. *left_vol = data->left_vol;
  97. *right_vol = data->right_vol;
  98. return 0;
  99. }
  100. int
  101. tumbler_set_register(uint reg, uint size, char *block)
  102. {
  103. if (i2c_smbus_write_block_data(tumbler_client, reg, size, block) < 0) {
  104. printk("tas3001c: I2C write failed n");  
  105. return -1; 
  106. }
  107. return 0;
  108. }
  109. int
  110. tumbler_get_pcm_lvl(uint *pcm_lvl)
  111. {
  112. struct tas_data_t *data;
  113. if (!tumbler_client)
  114. return -1;
  115. data = (struct tas_data_t *) (tumbler_client->data);
  116. *pcm_lvl = data->pcm_level;
  117. return 0;
  118. }
  119. int
  120. tumbler_get_treble(uint *treble)
  121. {
  122. struct tas_data_t *data;
  123. if (!tumbler_client)
  124. return -1;
  125. data = (struct tas_data_t *) (tumbler_client->data);
  126. *treble = data->treble;
  127. return 0;
  128. }
  129. int
  130. tumbler_get_bass(uint *bass)
  131. {
  132. struct tas_data_t *data;
  133. if (!tumbler_client)
  134. return -1;
  135. data = (struct tas_data_t *) (tumbler_client->data);
  136. *bass = data->bass;
  137. return 0;
  138. }
  139. int
  140. tumbler_set_bass(uint bass)
  141. {
  142. uint cur_bass_pers = bass;
  143. char block;
  144. struct tas_data_t *data;
  145. if (!tumbler_client)
  146. return -1;
  147. data = (struct tas_data_t *) (tumbler_client->data);
  148. bass &= 0xff;
  149. if (bass > TAS_SETTING_MAX)
  150. bass = TAS_SETTING_MAX;
  151. bass = ((bass * 72) / TAS_SETTING_MAX) << 0;
  152. bass = tas_bass_table[bass];
  153. block = (bass >> 0)  & 0xff;
  154. if (tumbler_set_register(TAS_SET_BASS, &block) < 0) {
  155. printk("tas3001c: failed to set bass n");  
  156. return -1; 
  157. }
  158. data->bass = cur_bass_pers;
  159. return 0;
  160. }
  161. int
  162. tumbler_set_treble(uint treble)
  163. {
  164. uint cur_treble_pers = treble;
  165. char block;
  166. struct tas_data_t *data;
  167. if (!tumbler_client)
  168. return -1;
  169. data = (struct tas_data_t *) (tumbler_client->data);
  170. treble &= 0xff;
  171. if (treble > TAS_SETTING_MAX)
  172. treble = TAS_SETTING_MAX;
  173. treble = ((treble * 72) / TAS_SETTING_MAX) << 0;
  174. treble = tas_treble_table[treble];
  175. block = (treble >> 0)  & 0xff;
  176. if (tumbler_set_register(TAS_SET_TREBLE, &block) < 0) {
  177. printk("tas3001c: failed to set treble n");  
  178. return -1; 
  179. }
  180. data->treble = cur_treble_pers;
  181. return 0;
  182. }
  183. int
  184. tumbler_set_pcm_lvl(uint pcm_lvl)
  185. {
  186. uint pcm_lvl_pers = pcm_lvl;
  187. unsigned char block[3];
  188. struct tas_data_t *data;
  189. if (!tumbler_client)
  190. return -1;
  191. data = (struct tas_data_t *) (tumbler_client->data);
  192. pcm_lvl &= 0xff;
  193. if (pcm_lvl > TAS_SETTING_MAX)
  194. pcm_lvl = TAS_SETTING_MAX;
  195. pcm_lvl = ((pcm_lvl * 176) / TAS_SETTING_MAX) << 0;
  196. pcm_lvl = tas_input_table[pcm_lvl];
  197. block[0] = (pcm_lvl >> 16) & 0xff;
  198. block[1] = (pcm_lvl >> 8)  & 0xff;
  199. block[2] = (pcm_lvl >> 0)  & 0xff;
  200. if (tumbler_set_register(TAS_SET_MIXER1, block) < 0) {
  201. printk("tas3001c: failed to set input level n");  
  202. return -1; 
  203. }
  204. data->pcm_level = pcm_lvl_pers;
  205. return 0;
  206. }
  207. int
  208. tumbler_set_volume(uint left_vol, uint right_vol)
  209. {
  210. uint left_vol_pers = left_vol;
  211. uint right_vol_pers = right_vol;
  212. unsigned char block[6];
  213. struct tas_data_t *data;
  214. if (!tumbler_client)
  215. return -1;
  216. data = (struct tas_data_t *) (tumbler_client->data);
  217. left_vol &= 0xff;
  218. if (left_vol > TAS_SETTING_MAX)
  219. left_vol = TAS_SETTING_MAX;
  220. right_vol = (right_vol >> 8) & 0xff;
  221. if (right_vol > TAS_SETTING_MAX)
  222. right_vol = TAS_SETTING_MAX;
  223. left_vol = ((left_vol * 176) / TAS_SETTING_MAX) << 0;
  224. right_vol = ((right_vol * 176) / TAS_SETTING_MAX) << 0;
  225. left_vol = tas_volume_table[left_vol];
  226. right_vol = tas_volume_table[right_vol];
  227. block[0] = (left_vol >> 16) & 0xff;
  228. block[1] = (left_vol >> 8)  & 0xff;
  229. block[2] = (left_vol >> 0)  & 0xff;
  230. block[3] = (right_vol >> 16) & 0xff;
  231. block[4] = (right_vol >> 8)  & 0xff;
  232. block[5] = (right_vol >> 0)  & 0xff;
  233. if (tumbler_set_register(TAS_SET_VOLUME, block) < 0) {
  234. printk("tas3001c: failed to set volume n");  
  235. return -1; 
  236. }
  237. data->left_vol = left_vol_pers;
  238. data->right_vol = right_vol_pers;
  239. return 0;
  240. }
  241. int
  242. tumbler_leave_sleep(void)
  243. {
  244. /* Stub for now, but I have the details on low-power mode */
  245. if (!tumbler_client)
  246. return -1;
  247. return 0;
  248. }
  249. int
  250. tumbler_enter_sleep(void)
  251. {
  252. /* Stub for now, but I have the details on low-power mode */
  253. if (!tumbler_client)
  254. return -1;
  255. return 0;
  256. }
  257. static int
  258. tas_attach_adapter(struct i2c_adapter *adapter)
  259. {
  260. if (!strncmp(adapter->name, "mac-io", 6))
  261. tas_detect_client(adapter, tas_i2c_address);
  262. return 0;
  263. }
  264. static int
  265. tas_init_client(struct i2c_client * new_client)
  266. {
  267. /* Make sure something answers on the i2c bus
  268. */
  269. if (i2c_smbus_write_byte_data(new_client, 1, (1<<6)+(2<<4)+(2<<2)+0) < 0)
  270. return -1;
  271. tumbler_client = new_client;
  272. tumbler_set_volume(VOL_DEFAULT, VOL_DEFAULT);
  273. tumbler_set_pcm_lvl(INPUT_DEFAULT);
  274. tumbler_set_bass(BASS_DEFAULT);
  275. tumbler_set_treble(TREBLE_DEFAULT);
  276. return 0;
  277. }
  278. static int
  279. tas_detect_client(struct i2c_adapter *adapter, int address)
  280. {
  281. int rc = 0;
  282. struct i2c_client *new_client;
  283. struct tas_data_t *data;
  284. const char *client_name = "tas 3001c Digital Equalizer";
  285. new_client = kmalloc(
  286.      sizeof(struct i2c_client) + sizeof(struct tas_data_t),
  287.      GFP_KERNEL);
  288. if (!new_client) {
  289. rc = -ENOMEM;
  290. goto bail;
  291. }
  292. /* This is tricky, but it will set the data to the right value. */
  293. new_client->data = new_client + 1;
  294. data = (struct tas_data_t *) (new_client->data);
  295. new_client->addr = address;
  296. new_client->data = data;
  297. new_client->adapter = adapter;
  298. new_client->driver = &tas_driver;
  299. new_client->flags = 0;
  300. strcpy(new_client->name,client_name);
  301. new_client->id = tas_id++; /* Automatically unique */
  302. if (tas_init_client(new_client)) {
  303. rc = -ENODEV;
  304. goto bail;
  305. }
  306. /* Tell the i2c layer a new client has arrived */
  307. if (i2c_attach_client(new_client)) {
  308. rc = -ENODEV;
  309. goto bail;
  310. }
  311. bail:
  312. if (rc && new_client)
  313. kfree(new_client);
  314. return rc;
  315. }
  316. static int
  317. tas_detach_client(struct i2c_client *client)
  318. {
  319. if (client == tumbler_client)
  320. tumbler_client = NULL;
  321. i2c_detach_client(client);
  322. kfree(client);
  323. return 0;
  324. }
  325. int
  326. tas_cleanup(void)
  327. {
  328. if (!tas_initialized)
  329. return -ENODEV;
  330. i2c_del_driver(&tas_driver);
  331. tas_initialized = 0;
  332. return 0;
  333. }
  334. int
  335. tas_init(void)
  336. {
  337. int rc;
  338. u32* paddr;
  339. if (tas_initialized)
  340. return 0;
  341. tas_node = find_devices("deq");
  342. if (tas_node == NULL)
  343. return -ENODEV;
  344. printk(KERN_INFO "tas3001c driver version %s (%s)n",TAS_VERSION,TAS_DATE);
  345. paddr = (u32 *)get_property(tas_node, "i2c-address", NULL);
  346. if (paddr) {
  347. tas_i2c_address = (*paddr) >> 1;
  348. printk(KERN_INFO "using i2c address: 0x%x from device-treen",
  349.        tas_i2c_address);
  350. } else    
  351. printk(KERN_INFO "using i2c address: 0x%x (default)n", tas_i2c_address);
  352. if ((rc = i2c_add_driver(&tas_driver))) {
  353. printk("tas3001c: Driver registration failed, module not inserted.n");
  354. tas_cleanup();
  355. return rc;
  356. }
  357. tas_initialized = 1;
  358. return 0;
  359. }