30 #include "../../lms2012/source/lms2012.h"
31 #include "../../lms2012/source/am1808.h"
37 #define MODULE_NAME "sound_module"
38 #define DEVICE1_NAME SOUND_DEVICE
40 static int ModuleInit(
void);
41 static void ModuleExit(
void);
45 #include <linux/kernel.h>
48 #include <linux/sched.h>
52 #include <linux/hrtimer.h>
55 #include <linux/hrtimer.h>
57 #include <linux/init.h>
58 #include <linux/uaccess.h>
59 #include <linux/debugfs.h>
61 #include <linux/ioport.h>
64 #include <linux/module.h>
65 #include <linux/miscdevice.h>
66 #include <asm/uaccess.h>
93 static ULONG *SYSCFG0;
95 static UWORD *eHRPWM0;
96 static void __iomem *GpioBase;
97 static UWORD Duration;
101 static SOUND SoundDefault;
102 static SOUND *pSound = &SoundDefault;
103 static struct hrtimer Device1Timer;
104 static ktime_t Device1Time;
111 #define CFGCHIP0 0x60 // 32 bit wide index into SYSCFG0
112 #define PLL_MASTER_LOCK 0x00001000
113 #define DEFAULT_FREQUENCY 16499 // 16499 should give 8 KHz
114 #define DEFAULT_LEVEL 1000 // 25% D.C.
118 static UWORD BufferReadPointer;
119 static UBYTE BufferReadIndex;
120 static UBYTE BufferWriteIndex;
124 #define TB_COUNT_UP 0x0 // TBCNT MODE bits
125 #define TB_DISABLE 0x0 // PHSEN bit
126 #define TB_ENABLE 0x4
127 #define TB_SHADOW 0x0 // PRDLD bit
128 #define TB_IMMEDIATE 0x8
129 #define TB_SYNC_DISABLE 0x30 // SYNCOSEL bits
130 #define TB_HDIV1 0x0 // HSPCLKDIV bits
131 #define TB_DIV1 0x0 // CLKDIV bits
132 #define TB_UP 0x2000 // PHSDIR bit
136 #define CC_CTR_A_ZERO 0x0 // LOADAMODE bits
137 #define CC_CTR_B_ZERO 0x0
138 #define CC_A_SHADOW 0x00 // SHDWAMODE and SHDWBMODE bits
139 #define CC_B_SHADOW 0x00
140 #define CC_B_NO_SHADOW 0x40
161 #define SOUND_RESERVED 0x0000
165 #define SOUND_CBD 0x0400
169 #define SOUND_CBU 0x0100
173 #define SOUND_CAD 0x0000
177 #define SOUND_CAU 0x0000
181 #define SOUND_PRD 0x0008
185 #define SOUND_ZRO 0x0002
190 #define SOUND_SYMM_TONE (SOUND_RESERVED +\
206 #define EHRPWMClkDisable {\
207 eHRPWM0[TBCTL] = 0xC033;\
217 #define EHRPWMClkEnable {\
218 eHRPWM0[TBCTL] = 0xC030; \
220 iowrite32((ioread32(&SYSCFG0[CFGCHIP0]) | PLL_MASTER_LOCK),&SYSCFG0[0x60]);\
224 #define EHRPWMClkEnableTone {\
225 eHRPWM0[TBCTL] = 0xDC30;\
227 iowrite32((ioread32(&SYSCFG0[CFGCHIP0]) | PLL_MASTER_LOCK),&SYSCFG0[0x60]);\
231 #define SETPwmPeriod(Prd) {\
232 eHRPWM0[TBPRD] = Prd; \
238 #define SETSoundLevel(Level) {\
239 eHRPWM0[CMPB] = Level; \
245 iowrite16(0x00, &eHRPWM0[TBCTL]);\
246 iowrite16(0x00, &eHRPWM0[CMPCTL]);\
250 #define SOUNDPwmModuleSetupPcm { \
255 eHRPWM0[TBPHS] = 0; \
256 eHRPWM0[TBCNT] = 0; \
258 eHRPWM0[CMPCTL] = (CC_B_SHADOW | CC_CTR_B_ZERO);\
259 eHRPWM0[AQCTLB] = 0x0102;\
263 #define SOUNDPwmModuleSetupTone { \
268 eHRPWM0[TBPHS] = 0; \
269 eHRPWM0[TBCNT] = 0; \
271 eHRPWM0[CMPCTL] = (CC_B_SHADOW | CC_CTR_B_ZERO);\
272 eHRPWM0[AQCTLB] = 0x0102;\
274 EHRPWMClkEnableTone;\
277 #define SOUNDEnable {\
278 (*SoundPin[SOUNDEN].pGpio).set_data = SoundPin[SOUNDEN].Mask;\
279 (*SoundPin[SOUNDEN].pGpio).dir &= ~SoundPin[SOUNDEN].Mask;\
282 #define SOUNDDisable {\
283 (*SoundPin[SOUNDEN].pGpio).clr_data = SoundPin[SOUNDEN].Mask;\
284 (*SoundPin[SOUNDEN].pGpio).dir &= ~SoundPin[SOUNDEN].Mask;\
287 #define SOUNDPwmPoweron {\
288 iowrite32(0x00000003, &PSC1[0x291]); \
289 iowrite32(0x00000003, &PSC1[0x48]); \
301 #if (HARDWARE == FINAL)
324 #if (HARDWARE == ONE2ONE)
359 #if (HARDWARE == EVALBOARD)
393 printk(
" GP%d_%-2d 0x%08X and 0x%08X or 0x%08X\n",(Pin >> 4),(Pin & 0x0F),(
u32)Reg,
MuxRegMap[Tmp].Mask,
MuxRegMap[Tmp].Mode);
401 printk(
" FUNCTION 0x%08X and 0x%08X or 0x%08X\n",(
u32)Reg,
MuxRegMap[Tmp].Mask,
MuxRegMap[Tmp].Mode);
410 printk(
"* GP%d_%-2d ********* ERROR not found *********\n",(Pin >> 4),(Pin & 0x0F));
432 SoundPin[Pin].
pGpio = (
struct gpio_controller *__iomem)(GpioBase + ((SoundPin[Pin].Pin >> 5) * 0x28) + 0x10);
433 SoundPin[Pin].
Mask = (1 << (SoundPin[Pin].
Pin & 0x1F));
457 if (request_mem_region(Address,Size,
MODULE_NAME) >= 0)
460 *Ptr = (
ULONG*)ioremap(Address,Size);
467 printk(
"%s memory Remapped from 0x%08lX\n",
DEVICE1_NAME,(
unsigned long)*Ptr);
475 printk(
"Memory remap ERROR");
484 printk(
"Region request error");
491 static void Device1TimerSetTiming(
ULONG Secs,
ULONG NanoSecs )
493 Device1Time = ktime_set(Secs, NanoSecs);
496 static void Device1TimerStart(
void)
498 hrtimer_start(&Device1Timer,Device1Time,HRTIMER_MODE_REL);
501 static void Device1TimerInitDuration(
void)
506 Sec = (
UWORD)(Duration / 1000);
507 nSec = (
ULONG)((Duration - Sec * 1000) * 1000000);
509 Device1TimerSetTiming(Sec, nSec);
513 static void Device1TimerCancel(
void)
516 hrtimer_cancel(&Device1Timer);
519 static void Device1TimerExit(
void)
521 Device1TimerCancel();
524 static enum hrtimer_restart Device1TimerInterrupt1(
struct hrtimer *pTimer)
528 enum hrtimer_restart ret = HRTIMER_RESTART;
530 if (0 < hrtimer_forward_now(pTimer,Device1Time))
547 if(SoundChunkSize[BufferReadIndex] > 0)
550 TempLevel = SoundBuffers[BufferReadIndex][BufferReadPointer++];
551 if(TempLevel == 0) TempLevel++;
554 TempLevel = (
UWORD)(Level * TempLevel);
557 SoundChunkSize[BufferReadIndex]--;
559 if(SoundChunkSize[BufferReadIndex] < 1)
561 BufferReadPointer = 0;
569 ret = HRTIMER_NORESTART;
573 (*pSound).Status = OK;
579 ret = HRTIMER_NORESTART;
583 (*pSound).Status = OK;
588 default: ret = HRTIMER_NORESTART;
595 static void Device1TimerInit8KHz(
void)
600 Device1TimerSetTiming(0, 125000);
604 static ssize_t Device1Write(
struct file *File,
const char *
Buffer,
size_t Count, loff_t *Data)
613 copy_from_user(CommandBuffer, Buffer, Count);
615 switch(CommandBuffer[0])
620 if(SoundChunkSize[BufferWriteIndex] == 0)
622 for(i = 1; i < Count; i++)
623 SoundBuffers[BufferWriteIndex][i-1] = CommandBuffer[i];
624 SoundChunkSize[BufferWriteIndex] = Count - 1;
627 BufferWriteIndex = 0;
628 BytesWritten = Count - 1;
636 Level = CommandBuffer[1];
637 Frequency = (
UWORD)(CommandBuffer[2] + (CommandBuffer[3] << 8));
638 Duration = (
UWORD) (CommandBuffer[4] + (CommandBuffer[5] << 8));
652 if (Level > 100) Level = 100;
654 PwmLevel = (
UWORD)(((ulong)(Period) * (ulong)(Level)) /(ulong)(200));
660 Device1TimerInitDuration();
676 Level = CommandBuffer[1];
680 BufferWriteIndex = 0;
682 BufferReadPointer = 0;
684 SoundChunkSize[i] = 0;
686 Device1TimerInit8KHz();
694 case BREAK: Device1TimerCancel();
698 (*pSound).Status = OK;
705 return (BytesWritten);
709 static ssize_t Device1Read(
struct file *File,
char *Buffer,
size_t Count,loff_t *Offset)
718 #define SHM_LENGTH (sizeof(SoundDefault))
719 #define NPAGES ((SHM_LENGTH + PAGE_SIZE - 1) / PAGE_SIZE)
720 static void *kmalloc_ptr;
722 static int Device1Mmap(
struct file *filp,
struct vm_area_struct *vma)
726 ret = remap_pfn_range(vma,vma->vm_start,virt_to_phys((
void*)((
unsigned long)pSound)) >> PAGE_SHIFT,vma->vm_end-vma->vm_start,PAGE_SHARED);
736 static const struct file_operations Device1Entries =
738 .owner = THIS_MODULE,
740 .write = Device1Write,
745 static struct miscdevice Device1 =
753 static int Device1Init(
void)
764 Result = misc_register(&Device1);
779 if ((kmalloc_ptr = kmalloc((
NPAGES + 2) * PAGE_SIZE, GFP_KERNEL)) !=
NULL)
781 pTmp = (
UWORD*)((((
unsigned long)kmalloc_ptr) + PAGE_SIZE - 1) & PAGE_MASK);
782 for (i = 0; i <
NPAGES * PAGE_SIZE; i += PAGE_SIZE)
784 SetPageReserved(virt_to_page(((
unsigned long)pTmp) + i));
786 pSound = (SOUND*)pTmp;
795 Device1TimerSetTiming(0, 125000);
796 hrtimer_init(&Device1Timer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);
798 Device1Timer.function = Device1TimerInterrupt1;
799 Device1TimerCancel();
809 (*pSound).Status = OK;
816 static void Device1Exit(
void)
822 misc_deregister(&Device1);
835 pTmp = (
UWORD*)pSound;
836 pSound = &SoundDefault;
838 for (i = 0; i <
NPAGES * PAGE_SIZE; i+= PAGE_SIZE)
840 ClearPageReserved(virt_to_page(((
unsigned long)pTmp) + i));
862 static int ModuleInit(
void)
867 printk(
"HwId = %d\n",HWID);
876 if (request_mem_region(DA8XX_GPIO_BASE,0xD8,
MODULE_NAME) >= 0)
878 GpioBase = (
void*)ioremap(DA8XX_GPIO_BASE,0xD8);
879 if (GpioBase !=
NULL)
897 static void ModuleExit(
void)
#define SOUNDPwmModuleSetupPcm
#define SOUND_MASTER_CLOCK
unsigned int ULONG
Basic Type used to symbolise 32 bit unsigned values.
MODULE_SUPPORTED_DEVICE(DEVICE1_NAME)
#define SOUND_FILE_BUFFER_SIZE
#define SOUND_BUFFER_COUNT
module_param(HwId, charp, 0)
unsigned char UBYTE
Basic Type used to symbolise 8 bit unsigned values.
MODULE_DESCRIPTION(MODULE_NAME)
unsigned short UWORD
Basic Type used to symbolise 16 bit unsigned values.
#define SOUNDPwmModuleSetupTone
void GetPeriphealBasePtr(ULONG Address, ULONG Size, ULONG **Ptr)
GetPeriphealBasePtr.
#define SETPwmPeriod(Prd)
#define SOUND_TONE_MASTER_CLOCK
#define SETSoundLevel(Level)
MODULE_AUTHOR("The LEGO Group")