jznomoney

Untitled

Mar 27th, 2011
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.85 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.  
  29. static struct spi_device *codec_dev;
  30. static struct mutex lock;
  31. static int aic3254_opend;
  32. static struct _CODEC_SPI_CMD **aic3254_uplink;
  33. static struct _CODEC_SPI_CMD **aic3254_downlink;
  34. static struct _CODEC_SPI_CMD **aic3254_minidsp;
  35. static int suspend_flag;
  36. static int aic3254_rx_mode;
  37. static int aic3254_tx_mode;
  38. static struct aic3254_ctl_ops default_ctl_ops;
  39. static struct aic3254_ctl_ops *ctl_ops = &default_ctl_ops;
  40.  
  41. struct ecodec_aic3254_state {
  42. int enabled;
  43. struct clk *rx_mclk;
  44. struct clk *rx_sclk;
  45. struct wake_lock idlelock;
  46. };
  47. static struct ecodec_aic3254_state codec_clk;
  48.  
  49. /* function prototype */
  50. int route_tx_enable(int, int);
  51. int route_rx_enable(int, int);
  52.  
  53. void aic3254_register_ctl_ops(struct aic3254_ctl_ops *ops)
  54. {
  55. ctl_ops = ops;
  56. }
  57.  
  58. static int codec_spi_write(unsigned char addr, unsigned char data)
  59. {
  60. unsigned char buffer[2];
  61. int rc;
  62.  
  63. if (!codec_dev)
  64. return 0;
  65.  
  66. codec_dev->bits_per_word = 16;
  67. buffer[0] = addr << 1;
  68. buffer[1] = data;
  69. rc = spi_write(codec_dev, buffer, 2);
  70.  
  71. return 1;
  72. }
  73.  
  74. static int codec_spi_read(unsigned char addr, unsigned char *data)
  75. {
  76. int rc;
  77. u8 buffer[2] = {0, 0};
  78. u8 result[2] = {0, 0};
  79.  
  80. codec_dev->bits_per_word = 16;
  81. buffer[0] = addr << 1 | 1;
  82. rc = spi_write_and_read(codec_dev, buffer, result, 2);
  83. if (rc < 0)
  84. return rc;
  85.  
  86. *data = result[1];
  87. return 0;
  88. }
  89.  
  90. static int aic3254_config(CODEC_SPI_CMD *cmds, int size)
  91. {
  92. int i, retry, ret;
  93. unsigned char data;
  94.  
  95. if (!codec_dev) {
  96. pr_err("%s: no spi device\n", __func__);
  97. return -EFAULT;
  98. }
  99.  
  100. if (cmds == NULL) {
  101. pr_err("%s: invalid spi parameters\n", __func__);
  102. return -EINVAL;
  103. } else
  104. pr_info("%s: size = %d\n", __func__, size);
  105.  
  106. /* when LCM power is off, spi transmission would fail sometime */
  107. if (suspend_flag && ctl_ops->panel_sleep_in) {
  108. ret = ctl_ops->panel_sleep_in();
  109. suspend_flag = 0;
  110. if (ret < 0)
  111. pr_err("%s: cannot make panel awake,"
  112. "it might failed on transmit SPI command\n"
  113. , __func__);
  114. else
  115. pr_info("%s: success on invoking panel_sleep_in\n"
  116. , __func__);
  117. }
  118.  
  119.  
  120. for (i = 0; i < size; i++) {
  121. switch (cmds[i].act) {
  122. case 'w':
  123. codec_spi_write(cmds[i].reg, cmds[i].data);
  124. break;
  125. case 'r':
  126. for (retry = AIC3254_MAX_RETRY; retry > 0; retry--) {
  127. ret = codec_spi_read(cmds[i].reg, &data);
  128. if (ret < 0)
  129. pr_err("%s: read fail %d, retry\n",
  130. __func__, ret);
  131. else if (data == cmds[i].data)
  132. break;
  133. hr_msleep(10);
  134. }
  135. if (retry <= 0)
  136. pr_err("%s: 3254 power down procedure"
  137. " ,flag 0x%02X=0x%02X(0x%02X)\n",
  138. __func__, cmds[i].reg,
  139. ret, cmds[i].data);
  140. break;
  141. case 'd':
  142. hr_msleep(cmds[i].data);
  143. break;
  144. default:
  145. break;
  146. }
  147. }
  148.  
  149. return 0;
  150. }
  151.  
  152. static int aic3254_config_ex(CODEC_SPI_CMD *cmds, int size)
  153. {
  154. int i = 0;
  155. int ret = -EINVAL;
  156. struct spi_transfer *spi_t_cmds = NULL;
  157. struct spi_message m;
  158. unsigned char *buffer = NULL;
  159. unsigned char *ptr = NULL;
  160.  
  161. if (!codec_dev) {
  162. pr_err("%s: no spi device\n", __func__);
  163. return -EFAULT;
  164. }
  165.  
  166. if (cmds == NULL || size == 0) {
  167. pr_err("%s: invalid spi parameters\n", __func__);
  168. return -EINVAL;
  169. } else {
  170. /* pr_info("%s: size = %d", __func__, size); */
  171. }
  172.  
  173. spi_t_cmds = (struct spi_transfer *) kmalloc(size*sizeof(struct spi_transfer), GFP_KERNEL);
  174. if (spi_t_cmds == NULL) {
  175. pr_err("%s: kmalloc spi transfer struct fail\n", __func__);
  176. goto error;
  177. } else
  178. memset(spi_t_cmds, 0, size*sizeof(struct spi_transfer));
  179.  
  180. buffer = (unsigned char *) kmalloc(size * 2 * sizeof(unsigned char), GFP_KERNEL);
  181. if (buffer == NULL) {
  182. pr_err("%s: kmalloc buffer fail\n", __func__);
  183. goto error;
  184. } else
  185. memset(buffer, 0, size*sizeof(CODEC_SPI_CMD)*sizeof(unsigned char));
  186.  
  187. spi_message_init(&m);
  188. for (i=0, ptr=buffer; i<size; i++, ptr+=2) {
  189. ptr[0] = cmds[i].reg << 1;
  190. ptr[1] = cmds[i].data;
  191.  
  192. spi_t_cmds[i].tx_buf = ptr;
  193. spi_t_cmds[i].len = 2;
  194. spi_message_add_tail(&spi_t_cmds[i], &m);
  195. }
  196. codec_dev->bits_per_word = 16;
  197. ret = spi_sync(codec_dev, &m);
  198.  
  199. error:
  200. if (buffer)
  201. kfree(buffer);
  202.  
  203. if (spi_t_cmds)
  204. kfree(spi_t_cmds);
  205. return ret;
  206. }
  207.  
  208. static void aic3254_tx_config(int mode)
  209. {
  210. /* use default setting when tx table doesn't be updated*/
  211. if (aic3254_uplink == NULL) {
  212. if (mode == UPLINK_OFF)
  213. route_tx_enable(mode, 0);
  214. else
  215. route_tx_enable(mode, 1);
  216. return;
  217. }
  218.  
  219. if (mode != UPLINK_OFF && mode != POWER_OFF) {
  220. /* uplink_Wakeup */
  221. aic3254_config(
  222. &aic3254_uplink[UPLINK_WAKEUP][1],
  223. aic3254_uplink[UPLINK_WAKEUP][0].data);
  224. }
  225.  
  226. /* route tx device */
  227. aic3254_config(&aic3254_uplink[mode][1],
  228. aic3254_uplink[mode][0].data);
  229. }
  230.  
  231. static void aic3254_rx_config(int mode)
  232. {
  233. /* use default setting when rx table doesn't be updated*/
  234. if (aic3254_downlink == NULL) {
  235. if (mode == DOWNLINK_OFF)
  236. route_rx_enable(mode, 0);
  237. else
  238. route_rx_enable(mode, 1);
  239. return;
  240. }
  241.  
  242. if (mode != DOWNLINK_OFF && mode != POWER_OFF) {
  243. /* Downlink Wakeup */
  244. aic3254_config(
  245. &aic3254_downlink[DOWNLINK_WAKEUP][1],
  246. aic3254_downlink[DOWNLINK_WAKEUP][0].data);
  247. }
  248.  
  249. /* route rx device */
  250. aic3254_config(&aic3254_downlink[mode][1],
  251. aic3254_downlink[mode][0].data);
  252. }
  253.  
  254. static void aic3254_powerdown(void)
  255. {
  256. struct ecodec_aic3254_state *drv = &codec_clk;
  257. if (aic3254_tx_mode != UPLINK_OFF || aic3254_rx_mode != DOWNLINK_OFF)
  258. return;
  259.  
  260. pr_info("%s: power off AIC3254\n", __func__);
  261. wake_lock(&drv->idlelock);
  262. if (aic3254_uplink != NULL)
  263. aic3254_config(&aic3254_uplink[POWER_OFF][1],
  264. aic3254_uplink[POWER_OFF][0].data);
  265. else
  266. aic3254_config(CODEC_POWER_OFF, ARRAY_SIZE(CODEC_POWER_OFF));
  267.  
  268. if (drv->enabled) {
  269. /* Disable MI2S RX master block */
  270. /* Disable MI2S RX bit clock */
  271. clk_disable(drv->rx_sclk);
  272. clk_disable(drv->rx_mclk);
  273. drv->enabled = 0;
  274. printk("%s: disable CLK\n", __func__);
  275. }
  276. wake_unlock(&drv->idlelock);
  277. return;
  278. }
  279. static void aic3254_loopback(int mode)
  280. {
  281. if (!(ctl_ops->lb_dsp_init &&
  282. ctl_ops->lb_receiver_imic &&
  283. ctl_ops->lb_speaker_imic &&
  284. ctl_ops->lb_headset_emic)) {
  285. pr_info("%s: AIC3254 LOOPBACK not supported\n", __func__);
  286. return;
  287. }
  288.  
  289. /* Init AIC3254 A00 */
  290. aic3254_config(ctl_ops->lb_dsp_init->data, ctl_ops->lb_dsp_init->len);
  291.  
  292. pr_info("%s: set AIC3254 in LOOPBACK mode\n", __func__);
  293. switch (mode) {
  294. case 0:
  295. /* receiver v.s. imic */
  296. aic3254_config(ctl_ops->lb_receiver_imic->data,
  297. ctl_ops->lb_receiver_imic->len);
  298. break;
  299. case 1:
  300. /* speaker v.s. imic */
  301. aic3254_config(ctl_ops->lb_speaker_imic->data,
  302. ctl_ops->lb_speaker_imic->len);
  303. break;
  304. case 2:
  305. /* headphone v.s emic */
  306. aic3254_config(ctl_ops->lb_headset_emic->data,
  307. ctl_ops->lb_headset_emic->len);
  308. case 13:
  309. /* headphone v.s 2nd mic */
  310. if (ctl_ops->lb_headset_bmic)
  311. aic3254_config(ctl_ops->lb_headset_bmic->data,
  312. ctl_ops->lb_headset_bmic->len);
  313. else
  314. pr_info("%s: 2nd mic loopback not supported\n", __func__);
  315. break;
  316. }
  317. }
  318.  
  319. int route_rx_enable(int path, int en)
  320. {
  321. pr_info("%s: (%d,%d) uses 3254 default setting\n", __func__, path, en);
  322. if (en) {
  323. /* Downlink_Wakeup */
  324. aic3254_config(CODEC_DOWNLINK_ON,
  325. ARRAY_SIZE(CODEC_DOWNLINK_ON));
  326. /* Path switching */
  327. switch (path) {
  328. case FM_OUT_HEADSET:
  329. /* FM headset */
  330. aic3254_config(FM_In_Headphone,
  331. ARRAY_SIZE(FM_In_Headphone));
  332. aic3254_config(FM_Out_Headphone,
  333. ARRAY_SIZE(FM_Out_Headphone));
  334. break;
  335. case FM_OUT_SPEAKER:
  336. /* FM speaker */
  337. aic3254_config(FM_In_SPK,
  338. ARRAY_SIZE(FM_In_SPK));
  339. aic3254_config(FM_Out_SPK,
  340. ARRAY_SIZE(FM_Out_SPK));
  341. break;
  342. default:
  343. /* By pass */
  344. aic3254_config(Downlink_IMIC_Receiver,
  345. ARRAY_SIZE(Downlink_IMIC_Receiver));
  346. break;
  347. }
  348. } else {
  349. /* Downlink_Off */
  350. aic3254_config(CODEC_DOWNLINK_OFF,
  351. ARRAY_SIZE(CODEC_DOWNLINK_OFF));
  352. }
  353.  
  354. return 0;
  355. }
  356.  
  357. int route_tx_enable(int path, int en)
  358. {
  359. pr_info("%s: (%d,%d) uses 3254 default setting\n", __func__, path, en);
  360. if (en) {
  361. /* Uplink_Wakeup */
  362. aic3254_config(CODEC_UPLINK_ON, ARRAY_SIZE(CODEC_UPLINK_ON));
  363. /* Path switching */
  364. switch (path) {
  365. case CALL_UPLINK_IMIC_RECEIVER:
  366. case CALL_UPLINK_IMIC_HEADSET:
  367. case CALL_UPLINK_IMIC_SPEAKER:
  368. case VOICERECORD_IMIC:
  369. /* By pass */
  370. aic3254_config(MECHA_Uplink_IMIC,
  371. ARRAY_SIZE(MECHA_Uplink_IMIC));
  372. break;
  373. case CALL_UPLINK_EMIC_HEADSET:
  374. case VOICERECORD_EMIC:
  375. aic3254_config(Uplink_EMIC,
  376. ARRAY_SIZE(Uplink_EMIC));
  377. break;
  378. }
  379. } else {
  380. /* Uplink_Off */
  381. aic3254_config(CODEC_UPLINK_OFF, ARRAY_SIZE(CODEC_UPLINK_OFF));
  382. }
  383.  
  384. return 0;
  385. }
  386.  
  387.  
  388. void aic3254_set_mic_bias(int en) {
  389.  
  390. if (en)
  391. aic3254_config(CODEC_MICBIAS_ON, ARRAY_SIZE(CODEC_MICBIAS_ON));
  392. else
  393. aic3254_config(CODEC_MICBIAS_OFF, ARRAY_SIZE(CODEC_MICBIAS_OFF));
  394. }
  395.  
  396. static int aic3254_set_config(int config_tbl, int idx, int en)
  397. {
  398. int len;
  399. struct ecodec_aic3254_state *drv = &codec_clk;
  400. pr_info("%s: table(0x%X) index(%d)\n", __func__, config_tbl, idx);
  401.  
  402. wake_lock(&drv->idlelock);
  403.  
  404. if (drv->enabled == 0) {
  405. /* enable MI2S RX master block */
  406. /* enable MI2S RX bit clock */
  407. clk_enable(drv->rx_mclk);
  408. clk_enable(drv->rx_sclk);
  409. printk("%s: enable CLK\n", __func__);
  410. drv->enabled = 1;
  411. }
  412.  
  413. switch (config_tbl) {
  414. case AIC3254_CONFIG_TX:
  415. /* TX */
  416. pr_info("%s: enable tx\n", __func__);
  417. if (en) {
  418. if (ctl_ops->tx_amp_enable)
  419. ctl_ops->tx_amp_enable(0);
  420.  
  421. aic3254_tx_config(idx);
  422. aic3254_tx_mode = idx;
  423.  
  424. if (ctl_ops->tx_amp_enable)
  425. ctl_ops->tx_amp_enable(1);
  426. } else {
  427. aic3254_tx_config(UPLINK_OFF);
  428. aic3254_tx_mode = UPLINK_OFF;
  429. }
  430. break;
  431. case AIC3254_CONFIG_RX:
  432. /* RX */
  433. pr_info("%s: enable rx\n", __func__);
  434. if (en) {
  435. if (ctl_ops->rx_amp_enable)
  436. ctl_ops->rx_amp_enable(0);
  437.  
  438. aic3254_rx_config(idx);
  439. aic3254_rx_mode = idx;
  440.  
  441. if (ctl_ops->rx_amp_enable)
  442. ctl_ops->rx_amp_enable(1);
  443. } else {
  444. aic3254_rx_config(DOWNLINK_OFF);
  445. aic3254_rx_mode = DOWNLINK_OFF;
  446. }
  447. break;
  448. case AIC3254_CONFIG_MEDIA:
  449. if (aic3254_minidsp == NULL)
  450. return -EFAULT;
  451. len = (aic3254_minidsp[idx][0].reg << 8)
  452. | aic3254_minidsp[idx][0].data;
  453.  
  454. pr_info("%s: miniDSP command len = %d\n", __func__, len);
  455. pr_info("%s: rx mode %d, tx mode %d\n",
  456. __func__, aic3254_rx_mode, aic3254_tx_mode);
  457.  
  458. if (ctl_ops->rx_amp_enable)
  459. ctl_ops->rx_amp_enable(0);
  460.  
  461. /* step 1: power off first */
  462. if (aic3254_rx_mode != DOWNLINK_OFF)
  463. aic3254_rx_config(DOWNLINK_OFF);
  464.  
  465. /* step 2: config DSP */
  466. aic3254_config(&aic3254_minidsp[idx][1], len);
  467.  
  468. /* step 3: switch back to original path */
  469. if (aic3254_rx_mode != DOWNLINK_OFF)
  470. aic3254_rx_config(aic3254_rx_mode);
  471. if (aic3254_tx_mode != UPLINK_OFF)
  472. aic3254_tx_config(aic3254_tx_mode);
  473.  
  474. if (ctl_ops->rx_amp_enable)
  475. ctl_ops->rx_amp_enable(1);
  476.  
  477. pr_info("%s: configure minidsp done\n", __func__);
  478. break;
  479. }
  480.  
  481. wake_unlock(&drv->idlelock);
  482. return 0;
  483. }
  484.  
  485. static int aic3254_open(struct inode *inode, struct file *pfile)
  486. {
  487. int ret = 0;
  488.  
  489. mutex_lock(&lock);
  490. if (aic3254_opend) {
  491. pr_err("%s: busy\n", __func__);
  492. ret = -EBUSY;
  493. } else
  494. aic3254_opend = 1;
  495. mutex_unlock(&lock);
  496.  
  497. return ret;
  498. }
  499.  
  500. static int aic3254_release(struct inode *inode, struct file *pfile)
  501. {
  502. mutex_lock(&lock);
  503. aic3254_opend = 0;
  504. mutex_unlock(&lock);
  505.  
  506. return 0;
  507. }
  508.  
  509. static int aic3254_ioctl(struct inode *inode, struct file *file,
  510. unsigned int cmd, unsigned long argc)
  511. {
  512. struct AIC3254_PARAM para;
  513. void *table;
  514. int ret = 0, i = 0, mem_size, volume = 0;
  515. CODEC_SPI_CMD reg[2];
  516. unsigned char data;
  517.  
  518. switch (cmd) {
  519. case AIC3254_SET_TX_PARAM:
  520. case AIC3254_SET_RX_PARAM:
  521. if (copy_from_user(&para, (void *)argc, sizeof(para))) {
  522. pr_err("%s: failed on copy_from_user\n", __func__);
  523. return -EFAULT;
  524. }
  525.  
  526. pr_info("%s: parameters(%d, %d, %p)\n", __func__,
  527. para.row_num, para.col_num, para.cmd_data);
  528. if (cmd == AIC3254_SET_TX_PARAM)
  529. table = aic3254_uplink[0];
  530. else
  531. table = aic3254_downlink[0];
  532.  
  533. /* confirm indicated size doesn't exceed the allocated one */
  534. if (para.row_num > IO_CTL_ROW_MAX
  535. || para.col_num != IO_CTL_COL_MAX) {
  536. pr_err("%s: data size mismatch with allocated"
  537. " memory (%d,%d)\n", __func__,
  538. IO_CTL_ROW_MAX, IO_CTL_COL_MAX);
  539. return -EFAULT;
  540. }
  541.  
  542. mem_size = para.row_num * para.col_num * sizeof(CODEC_SPI_CMD);
  543. if (copy_from_user(table, para.cmd_data, mem_size)) {
  544. pr_err("%s: failed on copy_from_user\n", __func__);
  545. return -EFAULT;
  546. }
  547.  
  548. /* invoking initialization procedure of AIC3254 */
  549. if (cmd == AIC3254_SET_TX_PARAM)
  550. aic3254_tx_config(INITIAL);
  551.  
  552. pr_info("%s: update table(%d,%d) successfully\n",
  553. __func__, para.row_num, para.col_num);
  554. break;
  555. case AIC3254_SET_DSP_PARAM:
  556. if (copy_from_user(&para, (void *)argc, sizeof(para))) {
  557. pr_err("%s: failed on copy_from_user\n", __func__);
  558. return -EFAULT;
  559. }
  560. pr_info("%s: parameters(%d, %d, %p)\n", __func__,
  561. para.row_num, para.col_num, para.cmd_data);
  562.  
  563. table = aic3254_minidsp[0];
  564.  
  565. /* confirm indicated size doesn't exceed the allocated one */
  566. if (para.row_num > MINIDSP_ROW_MAX
  567. || para.col_num != MINIDSP_COL_MAX) {
  568. pr_err("%s: data size mismatch with allocated"
  569. " memory (%d,%d)\n", __func__,
  570. MINIDSP_ROW_MAX, MINIDSP_COL_MAX);
  571. return -EFAULT;
  572. }
  573.  
  574. mem_size = para.row_num * para.col_num * sizeof(CODEC_SPI_CMD);
  575. if (copy_from_user(table, para.cmd_data, mem_size)) {
  576. pr_err("%s: failed on copy_from_user\n", __func__);
  577. return -EFAULT;
  578. }
  579.  
  580. pr_info("%s: update table(%d,%d) successfully\n",
  581. __func__, para.row_num, para.col_num);
  582. break;
  583. case AIC3254_CONFIG_TX:
  584. case AIC3254_CONFIG_RX:
  585. case AIC3254_CONFIG_MEDIA:
  586. if (copy_from_user(&i, (void *)argc, sizeof(int))) {
  587. pr_err("%s: failed on copy_from_user\n", __func__);
  588. return -EFAULT;
  589. }
  590. pr_info("%s: index %d for %X\n", __func__, i, cmd);
  591. ret = aic3254_set_config(cmd, i, 1);
  592. if (ret < 0)
  593. pr_err("%s: configure(%d) error %d\n",
  594. __func__, i, ret);
  595. break;
  596. case AIC3254_CONFIG_VOLUME_L:
  597. if (copy_from_user(&volume, (void *)argc, sizeof(int))) {
  598. pr_err("%s: failed on copy_from_user\n", __func__);
  599. return -EFAULT;
  600. }
  601.  
  602. if (volume < -127 || volume > 48) {
  603. pr_err("%s: volume out of range\n", __func__);
  604. return -EFAULT;
  605. }
  606.  
  607. pr_info("%s: AIC3254 config left volume %d\n",
  608. __func__, volume);
  609.  
  610. CODEC_SET_VOLUME_L[1].data = volume;
  611. aic3254_config_ex(CODEC_SET_VOLUME_L, ARRAY_SIZE(CODEC_SET_VOLUME_L));
  612. break;
  613. case AIC3254_CONFIG_VOLUME_R:
  614. if (copy_from_user(&volume, (void *)argc, sizeof(int))) {
  615. pr_err("%s: failed on copy_from_user\n", __func__);
  616. return -EFAULT;
  617. }
  618.  
  619. if (volume < -127 || volume > 48) {
  620. pr_err("%s: volume out of range\n", __func__);
  621. return -EFAULT;
  622. }
  623.  
  624. pr_info("%s: AIC3254 config right volume %d\n",
  625. __func__, volume);
  626.  
  627. CODEC_SET_VOLUME_R[1].data = volume;
  628. aic3254_config_ex(CODEC_SET_VOLUME_R, ARRAY_SIZE(CODEC_SET_VOLUME_R));
  629. break;
  630. case AIC3254_DUMP_PAGES:
  631. if (copy_from_user(&i, (void *)argc, sizeof(int))) {
  632. pr_err("%s: failed on copy_from_user\n", __func__);
  633. return -EFAULT;
  634. }
  635. if (i > AIC3254_MAX_PAGES) {
  636. pr_err("%s: invalid page number %d\n", __func__, i);
  637. return -EINVAL;
  638. }
  639.  
  640. pr_info("========== %s: dump page %d ==========\n",
  641. __func__, i);
  642. /* indicated page number to AIC3254 */
  643. codec_spi_write(0x00, i);
  644. for (i = 0; i < AIC3254_MAX_REGS; i++) {
  645. ret = codec_spi_read(i, &data);
  646. if (ret < 0)
  647. pr_err("read fail on register 0x%X\n", i);
  648. else
  649. pr_info("(0x%02X, 0x%02X)\n", i, data);
  650. }
  651. pr_info("=============================================\n");
  652. break;
  653. case AIC3254_WRITE_REG:
  654. if (copy_from_user(&reg, (void *)argc,
  655. sizeof(CODEC_SPI_CMD)*2)) {
  656. pr_err("%s: failed on copy_from_user\n", __func__);
  657. return -EFAULT;
  658. }
  659. pr_info("%s: command list (%c,%02X,%02X) (%c,%02X,%02X)\n",
  660. __func__, reg[0].act, reg[0].reg, reg[0].data,
  661. reg[1].act, reg[1].reg, reg[1].data);
  662. aic3254_config_ex(reg, 2);
  663. break;
  664. case AIC3254_READ_REG:
  665. if (copy_from_user(&reg, (void *)argc,
  666. sizeof(CODEC_SPI_CMD)*2)) {
  667. pr_err("%s: failed on copy_from_user\n", __func__);
  668. return -EFAULT;
  669. }
  670. for (i = 0; i < 2; i++) {
  671. if (reg[i].act == 'r' || reg[i].act == 'R')
  672. codec_spi_read(reg[i].reg, &reg[i].data);
  673. else if (reg[i].act == 'w' || reg[i].act == 'W')
  674. codec_spi_write(reg[i].reg, reg[i].data);
  675. else
  676. return -EINVAL;
  677. }
  678. if (copy_to_user((void *)argc, &reg, sizeof(CODEC_SPI_CMD)*2)) {
  679. pr_err("%s: failed on copy_to_user\n", __func__);
  680. return -EFAULT;
  681. }
  682. break;
  683. case AIC3254_POWERDOWN:
  684. aic3254_powerdown();
  685. break;
  686. case AIC3254_LOOPBACK:
  687. if (copy_from_user(&i, (void *)argc, sizeof(int))) {
  688. pr_err("%s: failed on copy_from_user\n", __func__);
  689. return -EFAULT;
  690. }
  691. pr_info("%s: index %d for LOOPBACK\n", __func__, i);
  692. aic3254_loopback(i);
  693. break;
  694. default:
  695. pr_err("%s: invalid command %d\n", __func__, _IOC_NR(cmd));
  696. ret = -EINVAL;
  697. }
  698.  
  699. return ret;
  700. }
  701.  
  702. static const struct file_operations aic3254_fops = {
  703. .owner = THIS_MODULE,
  704. .open = aic3254_open,
  705. .release = aic3254_release,
  706. .ioctl = aic3254_ioctl,
  707. };
  708.  
  709. static struct miscdevice aic3254_misc = {
  710. .minor = MISC_DYNAMIC_MINOR,
  711. .name = "codec_aic3254",
  712. .fops = &aic3254_fops,
  713. };
  714.  
  715. static CODEC_SPI_CMD** init_2d_array(int row_sz, int col_sz)
  716. {
  717. CODEC_SPI_CMD *table = NULL;
  718. CODEC_SPI_CMD **table_ptr = NULL;
  719. int i = 0;
  720.  
  721. table_ptr = kzalloc(row_sz * sizeof(CODEC_SPI_CMD *), GFP_KERNEL);
  722. table = kzalloc(row_sz * col_sz * sizeof(CODEC_SPI_CMD), GFP_KERNEL);
  723. if (table_ptr == NULL || table == NULL) {
  724. pr_err("%s: out of memory\n", __func__);
  725. kfree(table);
  726. kfree(table_ptr);
  727. } else
  728. for (i = 0; i < row_sz; i++)
  729. table_ptr[i] = (CODEC_SPI_CMD *)table + i * col_sz;
  730.  
  731. return table_ptr;
  732. }
  733.  
  734. static int spi_aic3254_probe(struct spi_device *aic3254)
  735. {
  736. pr_info("%s\n", __func__);
  737.  
  738. codec_dev = aic3254;
  739.  
  740. /* Boot up */
  741. #if 0
  742. aic3254_config(CODEC_INIT_REG, ARRAY_SIZE(CODEC_INIT_REG));
  743. aic3254_config(CODEC_DOWNLINK_OFF, ARRAY_SIZE(CODEC_DOWNLINK_OFF));
  744. aic3254_config(CODEC_UPLINK_OFF, ARRAY_SIZE(CODEC_UPLINK_OFF));
  745. aic3254_config(CODEC_POWER_OFF, ARRAY_SIZE(CODEC_POWER_OFF));
  746. #endif
  747.  
  748. aic3254_tx_mode = UPLINK_OFF;
  749. aic3254_rx_mode = DOWNLINK_OFF;
  750.  
  751. /* request space for firmware data of AIC3254 */
  752. aic3254_uplink = init_2d_array(IO_CTL_ROW_MAX, IO_CTL_COL_MAX);
  753. aic3254_downlink = init_2d_array(IO_CTL_ROW_MAX, IO_CTL_COL_MAX);
  754. aic3254_minidsp = init_2d_array(MINIDSP_ROW_MAX, MINIDSP_COL_MAX);
  755. return 0;
  756. }
  757.  
  758.  
  759. static int spi_aic3254_suspend(struct spi_device *aic3254, pm_message_t pmsg)
  760. {
  761. pr_info("%s\n", __func__);
  762. suspend_flag = 1;
  763. return 0;
  764. }
  765.  
  766. static int spi_aic3254_resume(struct spi_device *aic3254)
  767. {
  768. pr_info("%s\n", __func__);
  769. return 0;
  770. }
  771.  
  772. static int spi_aic3254_remove(struct spi_device *aic3254)
  773. {
  774. pr_info("%s\n", __func__);
  775.  
  776. /* release allocated memory in this driver */
  777. if (aic3254_uplink != NULL) {
  778. kfree(aic3254_uplink[0]);
  779. kfree(aic3254_uplink);
  780. aic3254_uplink = NULL;
  781. }
  782. if (aic3254_downlink != NULL) {
  783. kfree(aic3254_downlink[0]);
  784. kfree(aic3254_downlink);
  785. aic3254_downlink = NULL;
  786. }
  787. if (aic3254_minidsp != NULL) {
  788. kfree(aic3254_minidsp[0]);
  789. kfree(aic3254_minidsp);
  790. aic3254_minidsp = NULL;
  791. }
  792.  
  793. return 0;
  794. }
  795.  
  796. static struct spi_driver spi_aic3254 = {
  797. .driver = {
  798. .name = "spi_aic3254",
  799. .owner = THIS_MODULE,
  800. },
  801. .probe = spi_aic3254_probe,
  802. .suspend = spi_aic3254_suspend,
  803. .resume = spi_aic3254_resume,
  804. .remove = spi_aic3254_remove,
  805. };
  806.  
  807. static int __init spi_aic3254_init(void)
  808. {
  809. int ret = 0;
  810. struct ecodec_aic3254_state *codec_drv = &codec_clk;
  811.  
  812. pr_info("%s\n", __func__);
  813. mutex_init(&lock);
  814.  
  815. ret = spi_register_driver(&spi_aic3254);
  816. if (ret < 0) {
  817. pr_err("%s:failed to register spi driver(%d)\n", __func__, ret);
  818. return ret;
  819. }
  820.  
  821. ret = misc_register(&aic3254_misc);
  822. if (ret < 0) {
  823. pr_err("%s:failed to register misc device\n", __func__);
  824. spi_unregister_driver(&spi_aic3254);
  825. return ret;
  826. }
  827.  
  828. codec_drv->rx_mclk = clk_get(NULL, "mi2s_codec_rx_m_clk");
  829. if (IS_ERR(codec_drv->rx_mclk)) {
  830. pr_err("%s:failed to get mi2s mclk\n", __func__);
  831. misc_deregister(&aic3254_misc);
  832. spi_unregister_driver(&spi_aic3254);
  833. return -ENODEV;
  834. }
  835. codec_drv->rx_sclk = clk_get(NULL, "mi2s_codec_rx_s_clk");
  836. if (IS_ERR(codec_drv->rx_sclk)) {
  837. pr_err("%s:failed to get mi2s sclk\n", __func__);
  838. misc_deregister(&aic3254_misc);
  839. spi_unregister_driver(&spi_aic3254);
  840. clk_put(codec_drv->rx_mclk);
  841. return -ENODEV;
  842. }
  843.  
  844. wake_lock_init(&codec_drv->idlelock, WAKE_LOCK_IDLE,
  845. "aic3254_lock");
  846.  
  847. return 0;
  848. }
  849. module_init(spi_aic3254_init);
  850.  
  851. static void __exit spi_aic3254_exit(void)
  852. {
  853. struct ecodec_aic3254_state *codec_drv = &codec_clk;
  854.  
  855. spi_unregister_driver(&spi_aic3254);
  856. misc_deregister(&aic3254_misc);
  857.  
  858. clk_put(codec_drv->rx_mclk);
  859. clk_put(codec_drv->rx_sclk);
  860. return;
  861. }
  862. module_exit(spi_aic3254_exit);
  863.  
  864. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment