jznomoney

spi_aic3254.c

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