jznomoney

aic_3254.c from pyramid

Jul 29th, 2011
239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.74 KB | None | 0 0
  1. /* linux/driver/spi/spi_aic3254.c
  2. *
  3. *
  4. * Copyright (C) 2009 HTC Corporation.
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16.  
  17. #include <linux/kernel.h>
  18. #include <linux/init.h>
  19. #include <linux/miscdevice.h>
  20. #include <linux/fs.h>
  21. #include <linux/uaccess.h>
  22. #include <linux/spi/spi.h>
  23. #include <linux/spi/spi_aic3254.h>
  24. #include <linux/spi/spi_aic3254_reg.h>
  25. #include <linux/delay.h>
  26. #include <linux/clk.h>
  27. #include <linux/wakelock.h>
  28. #include <linux/rtc.h>
  29.  
  30. static struct spi_device *codec_dev;
  31. static struct mutex lock;
  32. static int aic3254_opend;
  33. static struct _CODEC_SPI_CMD **aic3254_uplink;
  34. static struct _CODEC_SPI_CMD **aic3254_downlink;
  35. static struct _CODEC_SPI_CMD **aic3254_minidsp;
  36. static uint8_t *bulk_tx;
  37. static int suspend_flag;
  38. static int aic3254_rx_mode;
  39. static int aic3254_tx_mode;
  40. static struct aic3254_ctl_ops default_ctl_ops;
  41. static struct aic3254_ctl_ops *ctl_ops = &default_ctl_ops;
  42. spinlock_t spinlock;
  43.  
  44. struct ecodec_aic3254_state {
  45. int enabled;
  46. struct clk *rx_mclk;
  47. struct clk *rx_sclk;
  48. struct wake_lock idlelock;
  49. struct wake_lock wakelock;
  50. };
  51. static struct ecodec_aic3254_state codec_clk;
  52.  
  53. /* function prototype */
  54. int route_tx_enable(int, int);
  55. int route_rx_enable(int, int);
  56. static void spi_aic3254_prevent_sleep(void);
  57. static void spi_aic3254_allow_sleep(void);
  58.  
  59. void aic3254_register_ctl_ops(struct aic3254_ctl_ops *ops)
  60. {
  61. ctl_ops = ops;
  62. }
  63.  
  64. static int codec_spi_write(unsigned char addr, unsigned char data)
  65. {
  66. unsigned char buffer[2];
  67. int rc;
  68.  
  69. if (!codec_dev)
  70. return 0;
  71.  
  72. codec_dev->bits_per_word = 16;
  73. buffer[0] = addr << 1;
  74. buffer[1] = data;
  75. rc = spi_write(codec_dev, buffer, 2);
  76.  
  77. return 1;
  78. }
  79.  
  80. static int codec_spi_read(unsigned char addr, unsigned char *data)
  81. {
  82. int rc;
  83. u8 buffer[2] = {0, 0};
  84. u8 result[2] = {0, 0};
  85.  
  86. codec_dev->bits_per_word = 16;
  87. buffer[0] = addr << 1 | 1;
  88. rc = spi_write_and_read(codec_dev, buffer, result, 2);
  89. if (rc < 0)
  90. return rc;
  91.  
  92. *data = result[1];
  93. return 0;
  94. }
  95.  
  96. static int32_t spi_write_table(CODEC_SPI_CMD *cmds, int num)
  97. {
  98. int i;
  99. int status = 0;
  100. struct spi_message m;
  101. struct spi_transfer tx_addr;
  102. spi_message_init(&m);
  103. memset(bulk_tx, 0, MINIDSP_COL_MAX * 2 * sizeof(uint8_t));
  104. memset(&tx_addr, 0, sizeof(struct spi_transfer));
  105.  
  106. for (i = 0; i < num ; i++) {
  107. bulk_tx[i * 2] = cmds[i].reg << 1;
  108. bulk_tx[i *2 + 1] = cmds[i].data;
  109. }
  110. tx_addr.tx_buf = bulk_tx;
  111. tx_addr.len = num * 2;
  112. tx_addr.cs_change = 1;
  113. tx_addr.bits_per_word = 16;
  114. spi_message_add_tail(&tx_addr, &m);
  115. if (codec_dev == NULL)
  116. status = -ESHUTDOWN;
  117. else
  118. status = spi_sync(codec_dev, &m);
  119. return status;
  120. }
  121.  
  122. static int aic3254_config(CODEC_SPI_CMD *cmds, int size)
  123. {
  124. int i, retry, ret;
  125. unsigned char data;
  126.  
  127. if (ctl_ops->spibus_enable)
  128. ctl_ops->spibus_enable(1);
  129.  
  130. if (!codec_dev) {
  131. pr_aud_err("%s: no spi device\n", __func__);
  132. return -EFAULT;
  133. }
  134.  
  135. if (cmds == NULL) {
  136. pr_aud_err("%s: invalid spi parameters\n", __func__);
  137. return -EINVAL;
  138. }
  139.  
  140. /* when LCM power is off, spi transmission would fail sometime */
  141. if (suspend_flag && ctl_ops->panel_sleep_in) {
  142. ret = ctl_ops->panel_sleep_in();
  143. suspend_flag = 0;
  144. if (ret < 0)
  145. pr_aud_err("%s: cannot make panel awake,"
  146. "it might failed on transmit SPI command\n"
  147. , __func__);
  148. else
  149. pr_aud_info("%s: success on invoking panel_sleep_in\n"
  150. , __func__);
  151. }
  152. /* large dsp image use bulk mode to transfer */
  153. /* avoid to bulk transfer on spi use ext_gpio_cs project */
  154. if (size < 1000 || codec_dev->ext_gpio_cs != 0) {
  155. for (i = 0; i < size; i++) {
  156. switch (cmds[i].act) {
  157. case 'w':
  158. codec_spi_write(cmds[i].reg, cmds[i].data);
  159. break;
  160. case 'r':
  161. for (retry = AIC3254_MAX_RETRY; retry > 0; retry--) {
  162. ret = codec_spi_read(cmds[i].reg, &data);
  163. if (ret < 0)
  164. pr_aud_err("%s: read fail %d, retry\n",
  165. __func__, ret);
  166. else if (data == cmds[i].data)
  167. break;
  168. hr_msleep(1);
  169. }
  170. if (retry <= 0)
  171. pr_aud_info("3254 power down procedure"
  172. " ,flag 0x%02X=0x%02X(0x%02X)\n",
  173. cmds[i].reg,
  174. ret, cmds[i].data);
  175. break;
  176. case 'd':
  177. hr_msleep(cmds[i].data);
  178. break;
  179. default:
  180. break;
  181. }
  182. }
  183. } else {
  184. /* use bulk to transfer large data */
  185. spi_write_table(cmds, size);
  186. }
  187. if (ctl_ops->spibus_enable)
  188. ctl_ops->spibus_enable(0);
  189. return 0;
  190. }
  191.  
  192. static int aic3254_config_ex(CODEC_SPI_CMD *cmds, int size)
  193. {
  194. int i = 0;
  195. int ret = -EINVAL;
  196. struct spi_transfer *spi_t_cmds = NULL;
  197. struct spi_message m;
  198. unsigned char *buffer = NULL;
  199. unsigned char *ptr = NULL;
  200.  
  201. if (!codec_dev) {
  202. pr_aud_err("%s: no spi device\n", __func__);
  203. return -EFAULT;
  204. }
  205.  
  206. if (cmds == NULL || size == 0) {
  207. pr_aud_err("%s: invalid spi parameters\n", __func__);
  208. return -EINVAL;
  209. } else {
  210. /* pr_info("%s: size = %d", __func__, size); */
  211. }
  212.  
  213. spi_t_cmds = (struct spi_transfer *) kmalloc(size*sizeof(struct spi_transfer), GFP_KERNEL);
  214. if (spi_t_cmds == NULL) {
  215. pr_aud_err("%s: kmalloc spi transfer struct fail\n", __func__);
  216. goto error;
  217. } else
  218. memset(spi_t_cmds, 0, size*sizeof(struct spi_transfer));
  219.  
  220. buffer = (unsigned char *) kmalloc(size * 2 * sizeof(unsigned char), GFP_KERNEL);
  221. if (buffer == NULL) {
  222. pr_aud_err("%s: kmalloc buffer fail\n", __func__);
  223. goto error;
  224. } else
  225. memset(buffer, 0, size*sizeof(CODEC_SPI_CMD)*sizeof(unsigned char));
  226.  
  227. if (ctl_ops->spibus_enable)
  228. ctl_ops->spibus_enable(1);
  229.  
  230. spi_message_init(&m);
  231. for (i=0, ptr=buffer; i<size; i++, ptr+=2) {
  232. ptr[0] = cmds[i].reg << 1;
  233. ptr[1] = cmds[i].data;
  234.  
  235. spi_t_cmds[i].tx_buf = ptr;
  236. spi_t_cmds[i].len = 2;
  237. spi_message_add_tail(&spi_t_cmds[i], &m);
  238. }
  239. codec_dev->bits_per_word = 16;
  240. ret = spi_sync(codec_dev, &m);
  241.  
  242. if (ctl_ops->spibus_enable)
  243. ctl_ops->spibus_enable(0);
  244.  
  245. error:
  246. if (buffer)
  247. kfree(buffer);
  248.  
  249. if (spi_t_cmds)
  250. kfree(spi_t_cmds);
  251. return ret;
  252. }
  253.  
  254. static void aic3254_tx_config(int mode)
  255. {
  256. /* use default setting when tx table doesn't be updated*/
  257. if (aic3254_uplink == NULL) {
  258. if (mode == UPLINK_OFF)
  259. route_tx_enable(mode, 0);
  260. else
  261. route_tx_enable(mode, 1);
  262. return;
  263. }
  264.  
  265. if (mode != UPLINK_OFF && mode != POWER_OFF) {
  266. /* uplink_Wakeup */
  267. pr_aud_info("uplink wakeup len(%d)\n",
  268. (aic3254_uplink[UPLINK_WAKEUP][0].data-1));
  269. aic3254_config(
  270. &aic3254_uplink[UPLINK_WAKEUP][1],
  271. aic3254_uplink[UPLINK_WAKEUP][0].data);
  272. }
  273.  
  274. /* route tx device */
  275. pr_aud_info("uplink TX %d len(%d)\n", mode,
  276. (aic3254_uplink[mode][0].data-1));
  277. aic3254_config(&aic3254_uplink[mode][1],
  278. aic3254_uplink[mode][0].data);
  279. }
  280.  
  281. static void aic3254_rx_config(int mode)
  282. {
  283. /* use default setting when rx table doesn't be updated*/
  284. if (aic3254_downlink == NULL) {
  285. if (mode == DOWNLINK_OFF)
  286. route_rx_enable(mode, 0);
  287. else
  288. route_rx_enable(mode, 1);
  289. return;
  290. }
  291.  
  292. if (mode != DOWNLINK_OFF && mode != POWER_OFF) {
  293. /* Downlink Wakeup */
  294. pr_aud_info("downlink wakeup len(%d)\n",
  295. (aic3254_downlink[DOWNLINK_WAKEUP][0].data-1));
  296. aic3254_config(
  297. &aic3254_downlink[DOWNLINK_WAKEUP][1],
  298. aic3254_downlink[DOWNLINK_WAKEUP][0].data);
  299. }
  300.  
  301. /* route rx device */
  302. pr_aud_info("downlink RX %d len(%d)\n", mode,
  303. (aic3254_downlink[mode][0].data-1));
  304. aic3254_config(&aic3254_downlink[mode][1],
  305. aic3254_downlink[mode][0].data);
  306. }
  307.  
  308. static void aic3254_powerdown(void)
  309. {
  310. int64_t t1, t2;
  311. #if defined(CONFIG_ARCH_MSM7X30)
  312. struct ecodec_aic3254_state *drv = &codec_clk;
  313. #endif
  314.  
  315.  
  316. if (aic3254_tx_mode != UPLINK_OFF || aic3254_rx_mode != DOWNLINK_OFF)
  317. return;
  318.  
  319. t1 = ktime_to_ms(ktime_get());
  320.  
  321. spi_aic3254_prevent_sleep();
  322. if (aic3254_uplink != NULL) {
  323. pr_aud_info("power off AIC3254 len(%d)++\n",
  324. (aic3254_uplink[POWER_OFF][0].data-1));
  325. aic3254_config(&aic3254_uplink[POWER_OFF][1],
  326. aic3254_uplink[POWER_OFF][0].data);
  327. } else {
  328. pr_aud_info("power off AIC3254 len(%d)++\n",
  329. (ARRAY_SIZE(CODEC_POWER_OFF)));
  330. aic3254_config(CODEC_POWER_OFF, ARRAY_SIZE(CODEC_POWER_OFF));
  331. }
  332.  
  333. #if defined(CONFIG_ARCH_MSM7X30)
  334. if (drv->enabled) {
  335. /* Disable MI2S RX master block */
  336. /* Disable MI2S RX bit clock */
  337. clk_disable(drv->rx_sclk);
  338. clk_disable(drv->rx_mclk);
  339. drv->enabled = 0;
  340. printk("%s: disable CLK\n", __func__);
  341. }
  342. #endif
  343.  
  344. spi_aic3254_allow_sleep();
  345.  
  346. t2 = ktime_to_ms(ktime_get())-t1;
  347. pr_aud_info("power off AIC3254 %lldms --\n", t2);
  348. return;
  349. }
  350. static void aic3254_loopback(int mode)
  351. {
  352. if (!(ctl_ops->lb_dsp_init &&
  353. ctl_ops->lb_receiver_imic &&
  354. ctl_ops->lb_speaker_imic &&
  355. ctl_ops->lb_headset_emic)) {
  356. pr_aud_info("%s: AIC3254 LOOPBACK not supported\n", __func__);
  357. return;
  358. }
  359.  
  360. /* Init AIC3254 A00 */
  361. aic3254_config(ctl_ops->lb_dsp_init->data, ctl_ops->lb_dsp_init->len);
  362.  
  363. pr_aud_info("%s: set AIC3254 in LOOPBACK mode\n", __func__);
  364. switch (mode) {
  365. case 0:
  366. /* receiver v.s. imic */
  367. aic3254_config(ctl_ops->lb_receiver_imic->data,
  368. ctl_ops->lb_receiver_imic->len);
  369. break;
  370. case 1:
  371. /* speaker v.s. imic */
  372. aic3254_config(ctl_ops->lb_speaker_imic->data,
  373. ctl_ops->lb_speaker_imic->len);
  374. break;
  375. case 2:
  376. /* headphone v.s emic */
  377. aic3254_config(ctl_ops->lb_headset_emic->data,
  378. ctl_ops->lb_headset_emic->len);
  379. break;
  380. case 13:
  381. /* receiver v.s 2nd mic */
  382. if (ctl_ops->lb_receiver_bmic)
  383. aic3254_config(ctl_ops->lb_receiver_bmic->data,
  384. ctl_ops->lb_receiver_bmic->len);
  385. else
  386. pr_aud_info("%s: receiver v.s. 2nd mic loopback not supported\n", __func__);
  387. break;
  388.  
  389. case 14:
  390. /* speaker v.s 2nd mic */
  391. if (ctl_ops->lb_speaker_bmic)
  392. aic3254_config(ctl_ops->lb_speaker_bmic->data,
  393. ctl_ops->lb_speaker_bmic->len);
  394. else
  395. pr_aud_info("%s: speaker v.s. 2nd mic loopback not supported\n", __func__);
  396. break;
  397.  
  398. case 15:
  399. /* headphone v.s 2nd mic */
  400. if (ctl_ops->lb_headset_bmic)
  401. aic3254_config(ctl_ops->lb_headset_bmic->data,
  402. ctl_ops->lb_headset_bmic->len);
  403. else
  404. pr_aud_info("%s: headset v.s. 2nd mic loopback not supported\n", __func__);
  405. break;
  406. default:
  407. break;
  408. }
  409. }
  410.  
  411. int route_rx_enable(int path, int en)
  412. {
  413. pr_aud_info("%s: (%d,%d) uses 3254 default setting\n", __func__, path, en);
  414. if (en) {
  415. /* Downlink_Wakeup */
  416. aic3254_config(CODEC_DOWNLINK_ON,
  417. ARRAY_SIZE(CODEC_DOWNLINK_ON));
  418. /* Path switching */
  419. switch (path) {
  420. case FM_OUT_HEADSET:
  421. /* FM headset */
  422. aic3254_config(FM_In_Headphone,
  423. ARRAY_SIZE(FM_In_Headphone));
  424. aic3254_config(FM_Out_Headphone,
  425. ARRAY_SIZE(FM_Out_Headphone));
  426. break;
  427. case FM_OUT_SPEAKER:
  428. /* FM speaker */
  429. aic3254_config(FM_In_SPK,
  430. ARRAY_SIZE(FM_In_SPK));
  431. aic3254_config(FM_Out_SPK,
  432. ARRAY_SIZE(FM_Out_SPK));
  433. break;
  434. default:
  435. /* By pass */
  436. aic3254_config(Downlink_IMIC_Receiver,
  437. ARRAY_SIZE(Downlink_IMIC_Receiver));
  438. break;
  439. }
  440. } else {
  441. /* Downlink_Off */
  442. aic3254_config(CODEC_DOWNLINK_OFF,
  443. ARRAY_SIZE(CODEC_DOWNLINK_OFF));
  444. }
  445.  
  446. return 0;
  447. }
  448.  
  449. int route_tx_enable(int path, int en)
  450. {
  451. pr_aud_info("%s: (%d,%d) uses 3254 default setting\n", __func__, path, en);
  452. if (en) {
  453. /* Uplink_Wakeup */
  454. aic3254_config(CODEC_UPLINK_ON, ARRAY_SIZE(CODEC_UPLINK_ON));
  455. /* Path switching */
  456. switch (path) {
  457. case CALL_UPLINK_IMIC_RECEIVER:
  458. case CALL_UPLINK_IMIC_HEADSET:
  459. case CALL_UPLINK_IMIC_SPEAKER:
  460. case VOICERECORD_IMIC:
  461. /* By pass */
  462. aic3254_config(MECHA_Uplink_IMIC,
  463. ARRAY_SIZE(MECHA_Uplink_IMIC));
  464. break;
  465. case CALL_UPLINK_EMIC_HEADSET:
  466. case VOICERECORD_EMIC:
  467. aic3254_config(Uplink_EMIC,
  468. ARRAY_SIZE(Uplink_EMIC));
  469. break;
  470. }
  471. } else {
  472. /* Uplink_Off */
  473. aic3254_config(CODEC_UPLINK_OFF, ARRAY_SIZE(CODEC_UPLINK_OFF));
  474. }
  475.  
  476. return 0;
  477. }
  478.  
  479.  
  480. void aic3254_set_mic_bias(int en) {
  481.  
  482. if (en)
  483. aic3254_config(CODEC_MICBIAS_ON, ARRAY_SIZE(CODEC_MICBIAS_ON));
  484. else
  485. aic3254_config(CODEC_MICBIAS_OFF, ARRAY_SIZE(CODEC_MICBIAS_OFF));
  486. }
  487.  
  488. static int aic3254_set_config(int config_tbl, int idx, int en)
  489. {
  490. int rc = 0, len = 0;
  491. int64_t t1, t2;
  492. #if defined(CONFIG_ARCH_MSM7X30)
  493. struct ecodec_aic3254_state *drv = &codec_clk;
  494. #endif
  495.  
  496. mutex_lock(&lock);
  497. spi_aic3254_prevent_sleep();
  498.  
  499. #if defined(CONFIG_ARCH_MSM7X30)
  500. if (drv->enabled == 0) {
  501. /* enable MI2S RX master block */
  502. /* enable MI2S RX bit clock */
  503. clk_enable(drv->rx_mclk);
  504. clk_enable(drv->rx_sclk);
  505. printk("%s: enable CLK\n", __func__);
  506. drv->enabled = 1;
  507. }
  508. #endif
  509.  
  510. switch (config_tbl) {
  511. case AIC3254_CONFIG_TX:
  512. /* TX */
  513. pr_aud_info("%s: enable tx\n", __func__);
  514. if (en) {
  515. if (ctl_ops->tx_amp_enable)
  516. ctl_ops->tx_amp_enable(0);
  517.  
  518. aic3254_tx_config(idx);
  519. aic3254_tx_mode = idx;
  520.  
  521. if (ctl_ops->tx_amp_enable)
  522. ctl_ops->tx_amp_enable(1);
  523. } else {
  524. aic3254_tx_config(UPLINK_OFF);
  525. aic3254_tx_mode = UPLINK_OFF;
  526. }
  527. break;
  528. case AIC3254_CONFIG_RX:
  529. /* RX */
  530. pr_aud_info("%s: enable rx\n", __func__);
  531. if (en) {
  532. if (ctl_ops->rx_amp_enable)
  533. ctl_ops->rx_amp_enable(0);
  534.  
  535. aic3254_rx_config(idx);
  536. aic3254_rx_mode = idx;
  537.  
  538. if (ctl_ops->rx_amp_enable)
  539. ctl_ops->rx_amp_enable(1);
  540. } else {
  541. aic3254_rx_config(DOWNLINK_OFF);
  542. aic3254_rx_mode = DOWNLINK_OFF;
  543. }
  544. break;
  545. case AIC3254_CONFIG_MEDIA:
  546. if (aic3254_minidsp == NULL) {
  547. rc = -EFAULT;
  548. break;
  549. }
  550.  
  551. len = (aic3254_minidsp[idx][0].reg << 8)
  552. | aic3254_minidsp[idx][0].data;
  553.  
  554. pr_aud_info("%s: configure miniDSP index(%d) len = %d ++\n",
  555. __func__, idx, len);
  556. pr_aud_info("%s: rx mode %d, tx mode %d\n",
  557. __func__, aic3254_rx_mode, aic3254_tx_mode);
  558.  
  559. t1 = ktime_to_ms(ktime_get());
  560.  
  561. if (ctl_ops->rx_amp_enable)
  562. ctl_ops->rx_amp_enable(0);
  563.  
  564. /* step 1: power off first */
  565. if (aic3254_rx_mode != DOWNLINK_OFF)
  566. aic3254_rx_config(DOWNLINK_OFF);
  567.  
  568. /* step 2: config DSP */
  569. aic3254_config(&aic3254_minidsp[idx][1], len);
  570.  
  571. /* step 3: switch back to original path */
  572. if (aic3254_rx_mode != DOWNLINK_OFF)
  573. aic3254_rx_config(aic3254_rx_mode);
  574. if (aic3254_tx_mode != UPLINK_OFF)
  575. aic3254_tx_config(aic3254_tx_mode);
  576.  
  577. t2 = ktime_to_ms(ktime_get())-t1;
  578.  
  579. if (ctl_ops->rx_amp_enable)
  580. ctl_ops->rx_amp_enable(1);
  581.  
  582. pr_aud_info("%s: configure miniDSP index(%d) time: %lldms --\n",
  583. __func__, idx, (t2));
  584. break;
  585. }
  586.  
  587. spi_aic3254_allow_sleep();
  588. mutex_unlock(&lock);
  589. return rc;
  590. }
  591.  
  592. static int aic3254_open(struct inode *inode, struct file *pfile)
  593. {
  594. int ret = 0;
  595.  
  596. mutex_lock(&lock);
  597. if (aic3254_opend) {
  598. pr_aud_err("%s: busy\n", __func__);
  599. ret = -EBUSY;
  600. } else
  601. aic3254_opend = 1;
  602. mutex_unlock(&lock);
  603.  
  604. return ret;
  605. }
  606.  
  607. static int aic3254_release(struct inode *inode, struct file *pfile)
  608. {
  609. mutex_lock(&lock);
  610. aic3254_opend = 0;
  611. mutex_unlock(&lock);
  612.  
  613. return 0;
  614. }
  615.  
  616. void aic3254_set_mode(int config, int mode)
  617. {
  618. mutex_lock(&lock);
  619. spi_aic3254_prevent_sleep();
  620.  
  621. switch (config) {
  622. case AIC3254_CONFIG_TX:
  623. /* TX */
  624. pr_aud_info("%s: AIC3254_CONFIG_TX mode = %d\n",
  625. __func__, mode);
  626. aic3254_tx_config(mode);
  627. aic3254_tx_mode = mode;
  628. break;
  629. case AIC3254_CONFIG_RX:
  630. /* RX */
  631. pr_aud_info("%s: AIC3254_CONFIG_RX mode = %d\n",
  632. __func__, mode);
  633. aic3254_rx_config(mode);
  634. if (mode == FM_OUT_SPEAKER)
  635. aic3254_tx_config(FM_IN_SPEAKER);
  636. else if (mode == FM_OUT_HEADSET)
  637. aic3254_tx_config(FM_IN_HEADSET);
  638. aic3254_rx_mode = mode;
  639. break;
  640. }
  641.  
  642. aic3254_powerdown();
  643.  
  644. spi_aic3254_allow_sleep();
  645. mutex_unlock(&lock);
  646. }
  647.  
  648. static int aic3254_ioctl(struct inode *inode, struct file *file,
  649. unsigned int cmd, unsigned long argc)
  650. {
  651. struct AIC3254_PARAM para;
  652. void *table;
  653. int ret = 0, i = 0, mem_size, volume = 0;
  654. CODEC_SPI_CMD reg[2];
  655. unsigned char data;
  656.  
  657. if (aic3254_uplink == NULL ||
  658. aic3254_downlink == NULL ||
  659. aic3254_minidsp == NULL) {
  660. pr_aud_err("%s: cmd 0x%x, invalid pointers\n", __func__, cmd);
  661. return -EFAULT;
  662. }
  663.  
  664. switch (cmd) {
  665. case AIC3254_SET_TX_PARAM:
  666. case AIC3254_SET_RX_PARAM:
  667. if (copy_from_user(&para, (void *)argc, sizeof(para))) {
  668. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  669. return -EFAULT;
  670. }
  671.  
  672. pr_aud_info("%s: parameters(%d, %d, %p)\n", __func__,
  673. para.row_num, para.col_num, para.cmd_data);
  674. if (cmd == AIC3254_SET_TX_PARAM)
  675. table = aic3254_uplink[0];
  676. else
  677. table = aic3254_downlink[0];
  678.  
  679. /* confirm indicated size doesn't exceed the allocated one */
  680. if (para.row_num > IO_CTL_ROW_MAX
  681. || para.col_num != IO_CTL_COL_MAX) {
  682. pr_aud_err("%s: data size mismatch with allocated"
  683. " memory (%d,%d)\n", __func__,
  684. IO_CTL_ROW_MAX, IO_CTL_COL_MAX);
  685. return -EFAULT;
  686. }
  687.  
  688. mem_size = para.row_num * para.col_num * sizeof(CODEC_SPI_CMD);
  689. if (copy_from_user(table, para.cmd_data, mem_size)) {
  690. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  691. return -EFAULT;
  692. }
  693.  
  694. /* invoking initialization procedure of AIC3254 */
  695. if (cmd == AIC3254_SET_TX_PARAM)
  696. aic3254_tx_config(INITIAL);
  697.  
  698. pr_aud_info("%s: update table(%d,%d) successfully\n",
  699. __func__, para.row_num, para.col_num);
  700. break;
  701. case AIC3254_SET_DSP_PARAM:
  702. if (copy_from_user(&para, (void *)argc, sizeof(para))) {
  703. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  704. return -EFAULT;
  705. }
  706.  
  707. pr_aud_info("%s: parameters(%d, %d, %p)\n", __func__,
  708. para.row_num, para.col_num, para.cmd_data);
  709.  
  710. table = aic3254_minidsp[0];
  711.  
  712. /* confirm indicated size doesn't exceed the allocated one */
  713. if (para.row_num > MINIDSP_ROW_MAX
  714. || para.col_num != MINIDSP_COL_MAX) {
  715. pr_aud_err("%s: data size mismatch with allocated"
  716. " memory (%d,%d)\n", __func__,
  717. MINIDSP_ROW_MAX, MINIDSP_COL_MAX);
  718. return -EFAULT;
  719. }
  720.  
  721. mem_size = para.row_num * para.col_num * sizeof(CODEC_SPI_CMD);
  722. if (copy_from_user(table, para.cmd_data, mem_size)) {
  723. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  724. return -EFAULT;
  725. }
  726.  
  727. pr_aud_info("%s: update table(%d,%d) successfully\n",
  728. __func__, para.row_num, para.col_num);
  729. break;
  730. case AIC3254_CONFIG_TX:
  731. case AIC3254_CONFIG_RX:
  732. case AIC3254_CONFIG_MEDIA:
  733. if (copy_from_user(&i, (void *)argc, sizeof(int))) {
  734. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  735. return -EFAULT;
  736. }
  737. ret = aic3254_set_config(cmd, i, 1);
  738. if (ret < 0)
  739. pr_aud_err("%s: configure(%d) error %d\n",
  740. __func__, i, ret);
  741. break;
  742. case AIC3254_CONFIG_VOLUME_L:
  743. if (copy_from_user(&volume, (void *)argc, sizeof(int))) {
  744. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  745. return -EFAULT;
  746. }
  747.  
  748. if (volume < -127 || volume > 48) {
  749. pr_aud_err("%s: volume out of range\n", __func__);
  750. return -EFAULT;
  751. }
  752.  
  753. pr_aud_info("%s: AIC3254 config left volume %d\n",
  754. __func__, volume);
  755.  
  756. CODEC_SET_VOLUME_L[1].data = volume;
  757. aic3254_config_ex(CODEC_SET_VOLUME_L, ARRAY_SIZE(CODEC_SET_VOLUME_L));
  758. break;
  759. case AIC3254_CONFIG_VOLUME_R:
  760. if (copy_from_user(&volume, (void *)argc, sizeof(int))) {
  761. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  762. return -EFAULT;
  763. }
  764.  
  765. if (volume < -127 || volume > 48) {
  766. pr_aud_err("%s: volume out of range\n", __func__);
  767. return -EFAULT;
  768. }
  769.  
  770. pr_aud_info("%s: AIC3254 config right volume %d\n",
  771. __func__, volume);
  772.  
  773. CODEC_SET_VOLUME_R[1].data = volume;
  774. aic3254_config_ex(CODEC_SET_VOLUME_R, ARRAY_SIZE(CODEC_SET_VOLUME_R));
  775. break;
  776. case AIC3254_DUMP_PAGES:
  777. if (copy_from_user(&i, (void *)argc, sizeof(int))) {
  778. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  779. return -EFAULT;
  780. }
  781. if (i > AIC3254_MAX_PAGES) {
  782. pr_aud_err("%s: invalid page number %d\n", __func__, i);
  783. return -EINVAL;
  784. }
  785.  
  786. pr_aud_info("========== %s: dump page %d ==========\n",
  787. __func__, i);
  788. /* indicated page number to AIC3254 */
  789. if (ctl_ops->rx_amp_enable)
  790. ctl_ops->rx_amp_enable(1);
  791. codec_spi_write(0x00, i);
  792. for (i = 0; i < AIC3254_MAX_REGS; i++) {
  793. ret = codec_spi_read(i, &data);
  794. if (ret < 0)
  795. pr_aud_err("read fail on register 0x%X\n", i);
  796. else
  797. pr_aud_info("(0x%02X, 0x%02X)\n", i, data);
  798. }
  799. if (ctl_ops->rx_amp_enable)
  800. ctl_ops->rx_amp_enable(0);
  801. pr_aud_info("=============================================\n");
  802. break;
  803. case AIC3254_WRITE_REG:
  804. if (copy_from_user(&reg, (void *)argc,
  805. sizeof(CODEC_SPI_CMD)*2)) {
  806. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  807. return -EFAULT;
  808. }
  809. pr_aud_info("%s: command list (%c,%02X,%02X) (%c,%02X,%02X)\n",
  810. __func__, reg[0].act, reg[0].reg, reg[0].data,
  811. reg[1].act, reg[1].reg, reg[1].data);
  812. aic3254_config_ex(reg, 2);
  813. break;
  814. case AIC3254_READ_REG:
  815. if (copy_from_user(&reg, (void *)argc,
  816. sizeof(CODEC_SPI_CMD)*2)) {
  817. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  818. return -EFAULT;
  819. }
  820. if (ctl_ops->spibus_enable)
  821. ctl_ops->spibus_enable(1);
  822. for (i = 0; i < 2; i++) {
  823. if (reg[i].act == 'r' || reg[i].act == 'R')
  824. codec_spi_read(reg[i].reg, &reg[i].data);
  825. else if (reg[i].act == 'w' || reg[i].act == 'W')
  826. codec_spi_write(reg[i].reg, reg[i].data);
  827. else
  828. return -EINVAL;
  829. }
  830. if (ctl_ops->spibus_enable)
  831. ctl_ops->spibus_enable(0);
  832. if (copy_to_user((void *)argc, &reg, sizeof(CODEC_SPI_CMD)*2)) {
  833. pr_aud_err("%s: failed on copy_to_user\n", __func__);
  834. return -EFAULT;
  835. }
  836. break;
  837. case AIC3254_POWERDOWN:
  838. mutex_lock(&lock);
  839. aic3254_powerdown();
  840. mutex_unlock(&lock);
  841. break;
  842. case AIC3254_LOOPBACK:
  843. if (copy_from_user(&i, (void *)argc, sizeof(int))) {
  844. pr_aud_err("%s: failed on copy_from_user\n", __func__);
  845. return -EFAULT;
  846. }
  847. pr_aud_info("%s: index %d for LOOPBACK\n", __func__, i);
  848. aic3254_loopback(i);
  849. break;
  850. default:
  851. pr_aud_err("%s: invalid command %d\n", __func__, _IOC_NR(cmd));
  852. ret = -EINVAL;
  853. }
  854.  
  855. return ret;
  856. }
  857.  
  858. static const struct file_operations aic3254_fops = {
  859. .owner = THIS_MODULE,
  860. .open = aic3254_open,
  861. .release = aic3254_release,
  862. .ioctl = aic3254_ioctl,
  863. };
  864.  
  865. static struct miscdevice aic3254_misc = {
  866. .minor = MISC_DYNAMIC_MINOR,
  867. .name = "codec_aic3254",
  868. .fops = &aic3254_fops,
  869. };
  870.  
  871. static CODEC_SPI_CMD** init_2d_array(int row_sz, int col_sz)
  872. {
  873. CODEC_SPI_CMD *table = NULL;
  874. CODEC_SPI_CMD **table_ptr = NULL;
  875. int i = 0;
  876.  
  877. table_ptr = kzalloc(row_sz * sizeof(CODEC_SPI_CMD *), GFP_KERNEL);
  878. table = kzalloc(row_sz * col_sz * sizeof(CODEC_SPI_CMD), GFP_KERNEL);
  879. if (table_ptr == NULL || table == NULL) {
  880. pr_aud_err("%s: out of memory\n", __func__);
  881. kfree(table);
  882. kfree(table_ptr);
  883. } else
  884. for (i = 0; i < row_sz; i++)
  885. table_ptr[i] = (CODEC_SPI_CMD *)table + i * col_sz;
  886.  
  887. return table_ptr;
  888. }
  889.  
  890. static int spi_aic3254_probe(struct spi_device *aic3254)
  891. {
  892. pr_aud_info("%s\n", __func__);
  893.  
  894. codec_dev = aic3254;
  895.  
  896. /* Boot up */
  897. #if 0
  898. aic3254_config(CODEC_INIT_REG, ARRAY_SIZE(CODEC_INIT_REG));
  899. aic3254_config(CODEC_DOWNLINK_OFF, ARRAY_SIZE(CODEC_DOWNLINK_OFF));
  900. aic3254_config(CODEC_UPLINK_OFF, ARRAY_SIZE(CODEC_UPLINK_OFF));
  901. aic3254_config(CODEC_POWER_OFF, ARRAY_SIZE(CODEC_POWER_OFF));
  902. #endif
  903.  
  904. aic3254_tx_mode = UPLINK_OFF;
  905. aic3254_rx_mode = DOWNLINK_OFF;
  906.  
  907. /* request space for firmware data of AIC3254 */
  908. aic3254_uplink = init_2d_array(IO_CTL_ROW_MAX, IO_CTL_COL_MAX);
  909. aic3254_downlink = init_2d_array(IO_CTL_ROW_MAX, IO_CTL_COL_MAX);
  910. aic3254_minidsp = init_2d_array(MINIDSP_ROW_MAX, MINIDSP_COL_MAX);
  911. bulk_tx = kcalloc(MINIDSP_COL_MAX * 2 , sizeof(uint8_t), GFP_KERNEL);
  912. spin_lock_init(&spinlock);
  913. return 0;
  914. }
  915.  
  916.  
  917. static int spi_aic3254_suspend(struct spi_device *aic3254, pm_message_t pmsg)
  918. {
  919. pr_aud_info("%s\n", __func__);
  920. suspend_flag = 1;
  921. return 0;
  922. }
  923.  
  924. static int spi_aic3254_resume(struct spi_device *aic3254)
  925. {
  926. pr_aud_info("%s\n", __func__);
  927. return 0;
  928. }
  929.  
  930. static int spi_aic3254_remove(struct spi_device *aic3254)
  931. {
  932. pr_aud_info("%s\n", __func__);
  933.  
  934. /* release allocated memory in this driver */
  935. if (aic3254_uplink != NULL) {
  936. kfree(aic3254_uplink[0]);
  937. kfree(aic3254_uplink);
  938. aic3254_uplink = NULL;
  939. }
  940. if (aic3254_downlink != NULL) {
  941. kfree(aic3254_downlink[0]);
  942. kfree(aic3254_downlink);
  943. aic3254_downlink = NULL;
  944. }
  945. if (aic3254_minidsp != NULL) {
  946. kfree(aic3254_minidsp[0]);
  947. kfree(aic3254_minidsp);
  948. aic3254_minidsp = NULL;
  949. }
  950. if (bulk_tx != NULL) {
  951. kfree(bulk_tx);
  952. bulk_tx = NULL;
  953. }
  954. return 0;
  955. }
  956.  
  957. static void spi_aic3254_prevent_sleep(void)
  958. {
  959. struct ecodec_aic3254_state *codec_drv = &codec_clk;
  960.  
  961. wake_lock(&codec_drv->wakelock);
  962. wake_lock(&codec_drv->idlelock);
  963. }
  964.  
  965. static void spi_aic3254_allow_sleep(void)
  966. {
  967. struct ecodec_aic3254_state *codec_drv = &codec_clk;
  968.  
  969. wake_unlock(&codec_drv->idlelock);
  970. wake_unlock(&codec_drv->wakelock);
  971. }
  972.  
  973. static struct spi_driver spi_aic3254 = {
  974. .driver = {
  975. .name = "spi_aic3254",
  976. .owner = THIS_MODULE,
  977. },
  978. .probe = spi_aic3254_probe,
  979. .suspend = spi_aic3254_suspend,
  980. .resume = spi_aic3254_resume,
  981. .remove = spi_aic3254_remove,
  982. };
  983.  
  984. static int __init spi_aic3254_init(void)
  985. {
  986. int ret = 0;
  987. struct ecodec_aic3254_state *codec_drv = &codec_clk;
  988.  
  989. pr_aud_info("%s\n", __func__);
  990. mutex_init(&lock);
  991.  
  992. ret = spi_register_driver(&spi_aic3254);
  993. if (ret < 0) {
  994. pr_aud_err("%s:failed to register spi driver(%d)\n", __func__, ret);
  995. return ret;
  996. }
  997.  
  998. ret = misc_register(&aic3254_misc);
  999. if (ret < 0) {
  1000. pr_aud_err("%s:failed to register misc device\n", __func__);
  1001. spi_unregister_driver(&spi_aic3254);
  1002. return ret;
  1003. }
  1004.  
  1005. #if defined(CONFIG_ARCH_MSM7X30)
  1006. codec_drv->rx_mclk = clk_get(NULL, "mi2s_codec_rx_m_clk");
  1007. if (IS_ERR(codec_drv->rx_mclk)) {
  1008. pr_aud_err("%s:failed to get mi2s mclk\n", __func__);
  1009. misc_deregister(&aic3254_misc);
  1010. spi_unregister_driver(&spi_aic3254);
  1011. return -ENODEV;
  1012. }
  1013. codec_drv->rx_sclk = clk_get(NULL, "mi2s_codec_rx_s_clk");
  1014. if (IS_ERR(codec_drv->rx_sclk)) {
  1015. pr_aud_err("%s:failed to get mi2s sclk\n", __func__);
  1016. misc_deregister(&aic3254_misc);
  1017. spi_unregister_driver(&spi_aic3254);
  1018. clk_put(codec_drv->rx_mclk);
  1019. return -ENODEV;
  1020. }
  1021. #endif
  1022.  
  1023. wake_lock_init(&codec_drv->idlelock, WAKE_LOCK_IDLE,
  1024. "aic3254_lock");
  1025. wake_lock_init(&codec_drv->wakelock, WAKE_LOCK_SUSPEND,
  1026. "aic3254_suspend_lock");
  1027.  
  1028. return 0;
  1029. }
  1030. module_init(spi_aic3254_init);
  1031.  
  1032. static void __exit spi_aic3254_exit(void)
  1033. {
  1034. struct ecodec_aic3254_state *codec_drv = &codec_clk;
  1035.  
  1036. spi_unregister_driver(&spi_aic3254);
  1037. misc_deregister(&aic3254_misc);
  1038.  
  1039. wake_lock_destroy(&codec_drv->wakelock);
  1040. wake_lock_destroy(&codec_drv->idlelock);
  1041.  
  1042. #if defined(CONFIG_ARCH_MSM7X30)
  1043. clk_put(codec_drv->rx_mclk);
  1044. clk_put(codec_drv->rx_sclk);
  1045. #endif
  1046. return;
  1047. }
  1048. module_exit(spi_aic3254_exit);
  1049.  
  1050. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment