1 /*
2 ** =============================================================================
3 ** Copyright (c) 2016 Texas Instruments Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify it under
6 ** the terms of the GNU General Public License as published by the Free Software
7 ** Foundation; version 2.
8 **
9 ** This program is distributed in the hope that it will be useful, but WITHOUT
10 ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 ** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 **
13 ** You should have received a copy of the GNU General Public License along with
14 ** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15 ** Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 **
17 ** File:
18 ** tas2555-misc.c
19 **
20 ** Description:
21 ** misc driver for Texas Instruments TAS2555 High Performance 4W Smart Amplifier
22 **
23 ** =============================================================================
24 */
26 #ifdef CONFIG_TAS2555_MISC_STEREO
28 #define DEBUG
29 #include <linux/module.h>
30 #include <linux/moduleparam.h>
31 #include <linux/init.h>
32 #include <linux/delay.h>
33 #include <linux/pm.h>
34 #include <linux/i2c.h>
35 #include <linux/gpio.h>
36 #include <linux/regulator/consumer.h>
37 #include <linux/firmware.h>
38 #include <linux/regmap.h>
39 #include <linux/of.h>
40 #include <linux/of_gpio.h>
41 #include <linux/slab.h>
42 #include <linux/syscalls.h>
43 #include <linux/fcntl.h>
44 #include <linux/miscdevice.h>
45 #include <asm/uaccess.h>
46 //#include <dt-bindings/sound/tas2555.h>
48 #include "tas2555.h"
49 #include "tas2555-core.h"
50 #include "tas2555-misc.h"
51 #include <linux/dma-mapping.h>
53 static int g_logEnable = 1;
54 static struct tas2555_priv *g_tas2555 = NULL;
56 static int tas2555_file_open(struct inode *inode, struct file *file)
57 {
58 struct tas2555_priv *pTAS2555 = g_tas2555;
60 if (!try_module_get(THIS_MODULE)) return -ENODEV;
62 file->private_data = (void*)pTAS2555;
64 if(g_logEnable) dev_info(pTAS2555->dev,
65 "%s\n", __FUNCTION__);
66 return 0;
67 }
69 static int tas2555_file_release(struct inode *inode, struct file *file)
70 {
71 struct tas2555_priv *pTAS2555 = (struct tas2555_priv *)file->private_data;
73 if(g_logEnable) dev_info(pTAS2555->dev,
74 "%s\n", __FUNCTION__);
76 file->private_data = (void*)NULL;
77 module_put(THIS_MODULE);
79 return 0;
80 }
82 static ssize_t tas2555_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
83 {
84 struct tas2555_priv *pTAS2555 = (struct tas2555_priv *)file->private_data;
85 int ret = 0;
86 unsigned int nValue = 0;
87 unsigned char value = 0;
88 unsigned char *p_kBuf = NULL;
90 mutex_lock(&pTAS2555->file_lock);
92 switch(pTAS2555->mnDBGCmd)
93 {
94 case TIAUDIO_CMD_REG_READ:
95 {
96 if(g_logEnable) dev_info(pTAS2555->dev,
97 "TIAUDIO_CMD_REG_READ: chn[%d], current_reg = 0x%x, count=%d\n",
98 pTAS2555->mnCurrentChannel,
99 pTAS2555->mnCurrentReg, (int)count);
100 if(count == 1){
101 ret = pTAS2555->read(pTAS2555,
102 pTAS2555->mnCurrentChannel,
103 pTAS2555->mnCurrentReg, &nValue);
104 if( 0 > ret) {
105 dev_err(pTAS2555->dev, "dev read fail %d\n", ret);
106 break;
107 }
109 value = (u8)nValue;
110 if(g_logEnable) dev_info(pTAS2555->dev,
111 "TIAUDIO_CMD_REG_READ: nValue=0x%x, value=0x%x\n",
112 nValue, value);
113 ret = copy_to_user(buf, &value, 1);
114 if (0 != ret) {
115 /* Failed to copy all the data, exit */
116 dev_err(pTAS2555->dev, "copy to user fail %d\n", ret);
117 }
118 }else if(count > 1){
119 p_kBuf = (unsigned char *)kzalloc(count, GFP_KERNEL);
120 if(p_kBuf != NULL){
121 ret = pTAS2555->bulk_read(pTAS2555,
122 pTAS2555->mnCurrentChannel,
123 pTAS2555->mnCurrentReg, p_kBuf, count);
124 if( 0 > ret) {
125 dev_err(pTAS2555->dev, "dev bulk read fail %d\n", ret);
126 }else{
127 ret = copy_to_user(buf, p_kBuf, count);
128 if (0 != ret) {
129 /* Failed to copy all the data, exit */
130 dev_err(pTAS2555->dev, "copy to user fail %d\n", ret);
131 }
132 }
134 kfree(p_kBuf);
135 }else{
136 dev_err(pTAS2555->dev, "read no mem\n");
137 }
138 }
139 }
140 break;
142 case TIAUDIO_CMD_PROGRAM:
143 {
144 if(g_logEnable) dev_info(pTAS2555->dev,
145 "TIAUDIO_CMD_PROGRAM: count = %d\n",
146 (int)count);
148 if(count == PROGRAM_BUF_SIZE){
149 p_kBuf = (unsigned char *)kzalloc(count, GFP_KERNEL);
150 if(p_kBuf != NULL){
151 TProgram * pProgram =
152 &(pTAS2555->mpFirmware->mpPrograms[pTAS2555->mnCurrentProgram]);
154 p_kBuf[0] = pTAS2555->mpFirmware->mnPrograms;
155 p_kBuf[1] = pTAS2555->mnCurrentProgram;
156 memcpy(&p_kBuf[2], pProgram->mpName, FW_NAME_SIZE);
157 strcpy(&p_kBuf[2+FW_NAME_SIZE], pProgram->mpDescription);
159 ret = copy_to_user(buf, p_kBuf, count);
160 if (0 != ret) {
161 /* Failed to copy all the data, exit */
162 dev_err(pTAS2555->dev, "copy to user fail %d\n", ret);
163 }
165 kfree(p_kBuf);
166 }else{
167 dev_err(pTAS2555->dev, "read no mem\n");
168 }
169 }else{
170 dev_err(pTAS2555->dev, "read buffer not sufficient\n");
171 }
172 }
173 break;
175 case TIAUDIO_CMD_CONFIGURATION:
176 {
177 if(g_logEnable) dev_info(pTAS2555->dev,
178 "TIAUDIO_CMD_CONFIGURATION: count = %d\n",
179 (int)count);
181 if(count == CONFIGURATION_BUF_SIZE){
182 p_kBuf = (unsigned char *)kzalloc(count, GFP_KERNEL);
183 if(p_kBuf != NULL){
184 TConfiguration * pConfiguration =
185 &(pTAS2555->mpFirmware->mpConfigurations[pTAS2555->mnCurrentConfiguration]);
187 p_kBuf[0] = pTAS2555->mpFirmware->mnConfigurations;
188 p_kBuf[1] = pTAS2555->mnCurrentConfiguration;
189 memcpy(&p_kBuf[2], pConfiguration->mpName, FW_NAME_SIZE);
190 p_kBuf[2+FW_NAME_SIZE] = pConfiguration->mnProgram;
191 p_kBuf[3+FW_NAME_SIZE] = pConfiguration->mnPLL;
192 p_kBuf[4+FW_NAME_SIZE] = (pConfiguration->mnSamplingRate&0x000000ff);
193 p_kBuf[5+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0x0000ff00)>>8);
194 p_kBuf[6+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0x00ff0000)>>16);
195 p_kBuf[7+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0xff000000)>>24);
196 strcpy(&p_kBuf[8+FW_NAME_SIZE], pConfiguration->mpDescription);
198 ret = copy_to_user(buf, p_kBuf, count);
199 if (0 != ret) {
200 /* Failed to copy all the data, exit */
201 dev_err(pTAS2555->dev, "copy to user fail %d\n", ret);
202 }
204 kfree(p_kBuf);
205 }else{
206 dev_err(pTAS2555->dev, "read no mem\n");
207 }
208 }else{
209 dev_err(pTAS2555->dev, "read buffer not sufficient\n");
210 }
211 }
212 break;
214 case TIAUDIO_CMD_FW_TIMESTAMP:
215 {
216 if(g_logEnable) dev_info(pTAS2555->dev,
217 "TIAUDIO_CMD_FW_TIMESTAMP: count = %d\n",
218 (int)count);
220 if(count == 4){
221 p_kBuf = (unsigned char *)kzalloc(count, GFP_KERNEL);
222 if(p_kBuf != NULL){
223 p_kBuf[0] = (pTAS2555->mpFirmware->mnTimeStamp&0x000000ff);
224 p_kBuf[1] = ((pTAS2555->mpFirmware->mnTimeStamp&0x0000ff00)>>8);
225 p_kBuf[2] = ((pTAS2555->mpFirmware->mnTimeStamp&0x00ff0000)>>16);
226 p_kBuf[3] = ((pTAS2555->mpFirmware->mnTimeStamp&0xff000000)>>24);
228 ret = copy_to_user(buf, p_kBuf, count);
229 if (0 != ret) {
230 /* Failed to copy all the data, exit */
231 dev_err(pTAS2555->dev, "copy to user fail %d\n", ret);
232 }
234 kfree(p_kBuf);
235 }else{
236 dev_err(pTAS2555->dev, "read no mem\n");
237 }
238 }
239 }
240 break;
242 case TIAUDIO_CMD_CALIBRATION:
243 {
244 if(g_logEnable) dev_info(pTAS2555->dev,
245 "TIAUDIO_CMD_CALIBRATION: count = %d\n",
246 (int)count);
248 if(count == 1){
249 unsigned char curCal = pTAS2555->mnCurrentCalibration;
250 ret = copy_to_user(buf, &curCal, 1);
251 if (0 != ret) {
252 /* Failed to copy all the data, exit */
253 dev_err(pTAS2555->dev, "copy to user fail %d\n", ret);
254 }
255 }
256 }
257 break;
259 case TIAUDIO_CMD_SAMPLERATE:
260 {
261 if(g_logEnable) dev_info(pTAS2555->dev,
262 "TIAUDIO_CMD_SAMPLERATE: count = %d\n",
263 (int)count);
264 if(count == 4){
265 p_kBuf = (unsigned char *)kzalloc(count, GFP_KERNEL);
266 if(p_kBuf != NULL){
267 TConfiguration *pConfiguration =
268 &(pTAS2555->mpFirmware->mpConfigurations[pTAS2555->mnCurrentConfiguration]);
270 p_kBuf[0] = (pConfiguration->mnSamplingRate&0x000000ff);
271 p_kBuf[1] = ((pConfiguration->mnSamplingRate&0x0000ff00)>>8);
272 p_kBuf[2] = ((pConfiguration->mnSamplingRate&0x00ff0000)>>16);
273 p_kBuf[3] = ((pConfiguration->mnSamplingRate&0xff000000)>>24);
275 ret = copy_to_user(buf, p_kBuf, count);
276 if (0 != ret) {
277 /* Failed to copy all the data, exit */
278 dev_err(pTAS2555->dev, "copy to user fail %d\n", ret);
279 }
281 kfree(p_kBuf);
282 }else{
283 dev_err(pTAS2555->dev, "read no mem\n");
284 }
285 }
286 }
287 break;
289 case TIAUDIO_CMD_BITRATE:
290 {
291 if(g_logEnable) dev_info(pTAS2555->dev,
292 "TIAUDIO_CMD_BITRATE: count = %d\n",
293 (int)count);
295 if(count == 1){
296 unsigned char bitRate = 0;
297 tas2555_get_bit_rate(pTAS2555,
298 pTAS2555->mnCurrentChannel, &bitRate);
299 ret = copy_to_user(buf, &bitRate, 1);
300 if (0 != ret) {
301 /* Failed to copy all the data, exit */
302 dev_err(pTAS2555->dev, "copy to user fail %d\n", ret);
303 }
304 }
305 }
306 break;
308 case TIAUDIO_CMD_DACVOLUME:
309 {
310 if(g_logEnable) dev_info(pTAS2555->dev,
311 "TIAUDIO_CMD_DACVOLUME: count = %d\n",
312 (int)count);
314 if(count == 1){
315 unsigned char volume = 0;
316 ret = tas2555_get_DAC_gain(pTAS2555,
317 pTAS2555->mnCurrentChannel, &volume);
318 if(ret >=0){
319 ret = copy_to_user(buf, &volume, 1);
320 if (0 != ret) {
321 /* Failed to copy all the data, exit */
322 dev_err(pTAS2555->dev, "copy to user fail %d\n", ret);
323 }
324 }
325 }
326 }
327 break;
328 }
329 pTAS2555->mnDBGCmd = 0;
331 mutex_unlock(&pTAS2555->file_lock);
332 return count;
333 }
335 static ssize_t tas2555_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
336 {
337 struct tas2555_priv *pTAS2555 = (struct tas2555_priv *)file->private_data;
338 int ret = 0;
339 // unsigned int value = 0;
340 unsigned char *p_kBuf = NULL;
341 unsigned int reg = 0;
342 enum channel chl;
343 unsigned int len = 0;
345 mutex_lock(&pTAS2555->file_lock);
347 p_kBuf = (unsigned char *)kzalloc(count, GFP_KERNEL);
348 if(p_kBuf == NULL) {
349 dev_err(pTAS2555->dev, "write no mem\n");
350 goto err;
351 }
353 ret = copy_from_user(p_kBuf, buf, count);
354 if (0 != ret) {
355 dev_err(pTAS2555->dev,"copy_from_user failed.\n");
356 goto err;
357 }
359 pTAS2555->mnDBGCmd = p_kBuf[0];
360 switch(pTAS2555->mnDBGCmd)
361 {
362 case TIAUDIO_CMD_REG_WITE:
363 if(count > 6){
364 chl = p_kBuf[1];
365 reg = ((unsigned int)p_kBuf[2] << 24) +
366 ((unsigned int)p_kBuf[3] << 16) +
367 ((unsigned int)p_kBuf[4] << 8) +
368 (unsigned int)p_kBuf[5];
369 len = count - 6;
370 if(len == 1){
371 ret = pTAS2555->write(pTAS2555,
372 chl, reg, p_kBuf[6]);
373 if(g_logEnable)
374 dev_info(pTAS2555->dev,
375 "TIAUDIO_CMD_REG_WITE,chn[%d], Reg=0x%x, Val=0x%x\n",
376 chl, reg, p_kBuf[6]);
377 }else{
378 ret = pTAS2555->bulk_write(pTAS2555,
379 chl, reg, &p_kBuf[6], len);
380 }
381 }else{
382 dev_err(pTAS2555->dev,"%s, write len fail, count=%d.\n",
383 __FUNCTION__, (int)count);
384 }
385 pTAS2555->mnDBGCmd = 0;
386 break;
388 case TIAUDIO_CMD_REG_READ:
389 if(count == 6){
390 pTAS2555->mnCurrentChannel = p_kBuf[1];
391 pTAS2555->mnCurrentReg = ((unsigned int)p_kBuf[2] << 24) +
392 ((unsigned int)p_kBuf[3] << 16) +
393 ((unsigned int)p_kBuf[4] << 8) +
394 (unsigned int)p_kBuf[5];
395 if(g_logEnable){
396 dev_info(pTAS2555->dev,
397 "TIAUDIO_CMD_REG_READ chl[%d], whole=0x%x\n",
398 pTAS2555->mnCurrentChannel,
399 pTAS2555->mnCurrentReg);
400 }
401 }else{
402 dev_err(pTAS2555->dev,"read len fail.\n");
403 }
404 break;
406 case TIAUDIO_CMD_DEBUG_ON:
407 {
408 if(count == 2){
409 g_logEnable = p_kBuf[1];
410 }
411 pTAS2555->mnDBGCmd = 0;
412 }
413 break;
415 case TIAUDIO_CMD_PROGRAM:
416 {
417 if(count == 2){
418 if(g_logEnable)
419 dev_info(pTAS2555->dev,
420 "TIAUDIO_CMD_PROGRAM, set to %d\n",
421 p_kBuf[1]);
422 tas2555_set_program(pTAS2555, p_kBuf[1]);
423 pTAS2555->mnDBGCmd = 0;
424 }
425 }
426 break;
428 case TIAUDIO_CMD_CONFIGURATION:
429 {
430 if(count == 2){
431 if(g_logEnable)
432 dev_info(pTAS2555->dev,
433 "TIAUDIO_CMD_CONFIGURATION, set to %d\n",
434 p_kBuf[1]);
435 tas2555_set_config(pTAS2555, p_kBuf[1]);
436 pTAS2555->mnDBGCmd = 0;
437 }
438 }
439 break;
441 case TIAUDIO_CMD_FW_TIMESTAMP:
442 /*let go*/
443 break;
445 case TIAUDIO_CMD_CALIBRATION:
446 {
447 if(count == 2){
448 if(g_logEnable)
449 dev_info(pTAS2555->dev,
450 "TIAUDIO_CMD_CALIBRATION, set to %d\n",
451 p_kBuf[1]);
452 tas2555_set_calibration(pTAS2555, p_kBuf[1]);
453 pTAS2555->mnDBGCmd = 0;
454 }
455 }
456 break;
458 case TIAUDIO_CMD_SAMPLERATE:
459 {
460 if(count == 5){
461 unsigned int nSampleRate = ((unsigned int)p_kBuf[1] << 24) +
462 ((unsigned int)p_kBuf[2] << 16) +
463 ((unsigned int)p_kBuf[3] << 8) +
464 (unsigned int)p_kBuf[4];
465 if(g_logEnable)
466 dev_info(pTAS2555->dev,
467 "TIAUDIO_CMD_SAMPLERATE, set to %d\n",
468 nSampleRate);
470 tas2555_set_sampling_rate(pTAS2555, nSampleRate);
471 }
472 }
473 break;
475 case TIAUDIO_CMD_BITRATE:
476 {
477 pTAS2555->mnCurrentChannel = p_kBuf[1];
478 if(count == 3){
479 if(g_logEnable)
480 dev_info(pTAS2555->dev,
481 "TIAUDIO_CMD_BITRATE, set to %d\n",
482 p_kBuf[1]);
484 tas2555_set_bit_rate(pTAS2555,
485 pTAS2555->mnCurrentChannel, p_kBuf[2]);
486 }
487 }
488 break;
490 case TIAUDIO_CMD_DACVOLUME:
491 {
492 pTAS2555->mnCurrentChannel = p_kBuf[1];
493 if(count == 3){
494 unsigned char volume;
495 volume = (p_kBuf[2] & 0x0f);
496 if(g_logEnable)
497 dev_info(pTAS2555->dev,
498 "TIAUDIO_CMD_DACVOLUME, set to %d\n",
499 volume);
501 tas2555_set_DAC_gain(pTAS2555,
502 pTAS2555->mnCurrentChannel, volume);
503 }
504 }
505 break;
507 case TIAUDIO_CMD_SPEAKER:
508 {
509 if(count == 2){
510 if(g_logEnable)
511 dev_info(pTAS2555->dev,
512 "TIAUDIO_CMD_SPEAKER, set to %d\n",
513 p_kBuf[1]);
514 tas2555_enable(pTAS2555, (p_kBuf[1]>0));
515 }
516 }
517 break;
519 case TIAUDIO_CMD_FW_RELOAD:
520 {
521 if(count == 1){
522 ret = request_firmware_nowait(THIS_MODULE, 1, TAS2555_FW_NAME,
523 pTAS2555->dev, GFP_KERNEL, pTAS2555, tas2555_fw_ready);
525 if(g_logEnable)
526 dev_info(pTAS2555->dev,
527 "TIAUDIO_CMD_FW_RELOAD: ret = %d\n",
528 ret);
529 }
531 }
532 break;
534 default:
535 pTAS2555->mnDBGCmd = 0;
536 break;
537 }
539 err:
540 if(p_kBuf != NULL)
541 kfree(p_kBuf);
543 mutex_unlock(&pTAS2555->file_lock);
545 return count;
546 }
548 static long tas2555_file_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
549 {
550 struct tas2555_priv *pTAS2555 = file->private_data;
551 int ret = 0;
553 mutex_lock(&pTAS2555->file_lock);
555 switch (cmd) {
556 case SMARTPA_SPK_DAC_VOLUME:
557 {
558 }
559 break;
561 case SMARTPA_SPK_POWER_ON:
562 {
563 tas2555_enable(pTAS2555, true);
564 }
565 break;
567 case SMARTPA_SPK_POWER_OFF:
568 {
569 tas2555_enable(pTAS2555, false);
570 }
571 break;
573 case SMARTPA_SPK_SWITCH_PROGRAM:
574 {
575 tas2555_set_program(pTAS2555, arg);
576 }
577 break;
579 case SMARTPA_SPK_SWITCH_CONFIGURATION:
580 {
581 tas2555_set_config(pTAS2555, arg);
582 }
583 break;
585 case SMARTPA_SPK_SWITCH_CALIBRATION:
586 {
587 tas2555_set_calibration(pTAS2555, arg);
588 }
589 break;
591 case SMARTPA_SPK_SET_SAMPLERATE:
592 {
593 tas2555_set_sampling_rate(pTAS2555, arg);
594 }
595 break;
597 case SMARTPA_SPK_SET_BITRATE:
598 {
599 tas2555_set_bit_rate(pTAS2555, channel_both, arg);
600 }
601 break;
602 }
604 mutex_unlock(&pTAS2555->file_lock);
605 return ret;
606 }
608 static struct file_operations fops =
609 {
610 .owner = THIS_MODULE,
611 .read = tas2555_file_read,
612 .write = tas2555_file_write,
613 .unlocked_ioctl = tas2555_file_unlocked_ioctl,
614 .open = tas2555_file_open,
615 .release = tas2555_file_release,
616 };
618 #define MODULE_NAME "tas2555s"
619 static struct miscdevice tas2555_misc =
620 {
621 .minor = MISC_DYNAMIC_MINOR,
622 .name = MODULE_NAME,
623 .fops = &fops,
624 };
626 int tas2555_register_misc(struct tas2555_priv * pTAS2555)
627 {
628 int ret = 0;
630 g_tas2555 = pTAS2555;
632 ret = misc_register(&tas2555_misc);
633 if (ret) {
634 dev_err(pTAS2555->dev, "TAS2555 misc fail: %d\n", ret);
635 }
637 dev_info(pTAS2555->dev, "%s, leave\n", __FUNCTION__);
639 return ret;
640 }
642 int tas2555_deregister_misc(struct tas2555_priv * pTAS2555)
643 {
644 misc_deregister(&tas2555_misc);
645 return 0;
646 }
648 MODULE_AUTHOR("Texas Instruments Inc.");
649 MODULE_DESCRIPTION("TAS2555 Misc Smart Amplifier driver");
650 MODULE_LICENSE("GPLv2");
651 #endif