symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/cs4231.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * QEMU Crystal CS4231 audio chip emulation
       
     3  *
       
     4  * Copyright (c) 2006 Fabrice Bellard
       
     5  *
       
     6  * Permission is hereby granted, free of charge, to any person obtaining a copy
       
     7  * of this software and associated documentation files (the "Software"), to deal
       
     8  * in the Software without restriction, including without limitation the rights
       
     9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
    10  * copies of the Software, and to permit persons to whom the Software is
       
    11  * furnished to do so, subject to the following conditions:
       
    12  *
       
    13  * The above copyright notice and this permission notice shall be included in
       
    14  * all copies or substantial portions of the Software.
       
    15  *
       
    16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
       
    19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       
    22  * THE SOFTWARE.
       
    23  */
       
    24 #include "hw.h"
       
    25 #include "sun4m.h"
       
    26 
       
    27 /* debug CS4231 */
       
    28 //#define DEBUG_CS
       
    29 
       
    30 /*
       
    31  * In addition to Crystal CS4231 there is a DMA controller on Sparc.
       
    32  */
       
    33 #define CS_SIZE 0x40
       
    34 #define CS_REGS 16
       
    35 #define CS_DREGS 32
       
    36 #define CS_MAXDREG (CS_DREGS - 1)
       
    37 
       
    38 typedef struct CSState {
       
    39     uint32_t regs[CS_REGS];
       
    40     uint8_t dregs[CS_DREGS];
       
    41     void *intctl;
       
    42 } CSState;
       
    43 
       
    44 #define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG)
       
    45 #define CS_VER 0xa0
       
    46 #define CS_CDC_VER 0x8a
       
    47 
       
    48 #ifdef DEBUG_CS
       
    49 #define DPRINTF(fmt, args...)                           \
       
    50     do { printf("CS: " fmt , ##args); } while (0)
       
    51 #else
       
    52 #define DPRINTF(fmt, args...)
       
    53 #endif
       
    54 
       
    55 static void cs_reset(void *opaque)
       
    56 {
       
    57     CSState *s = opaque;
       
    58 
       
    59     memset(s->regs, 0, CS_REGS * 4);
       
    60     memset(s->dregs, 0, CS_DREGS);
       
    61     s->dregs[12] = CS_CDC_VER;
       
    62     s->dregs[25] = CS_VER;
       
    63 }
       
    64 
       
    65 static uint32_t cs_mem_readl(void *opaque, target_phys_addr_t addr)
       
    66 {
       
    67     CSState *s = opaque;
       
    68     uint32_t saddr, ret;
       
    69 
       
    70     saddr = addr >> 2;
       
    71     switch (saddr) {
       
    72     case 1:
       
    73         switch (CS_RAP(s)) {
       
    74         case 3: // Write only
       
    75             ret = 0;
       
    76             break;
       
    77         default:
       
    78             ret = s->dregs[CS_RAP(s)];
       
    79             break;
       
    80         }
       
    81         DPRINTF("read dreg[%d]: 0x%8.8x\n", CS_RAP(s), ret);
       
    82         break;
       
    83     default:
       
    84         ret = s->regs[saddr];
       
    85         DPRINTF("read reg[%d]: 0x%8.8x\n", saddr, ret);
       
    86         break;
       
    87     }
       
    88     return ret;
       
    89 }
       
    90 
       
    91 static void cs_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
       
    92 {
       
    93     CSState *s = opaque;
       
    94     uint32_t saddr;
       
    95 
       
    96     saddr = addr >> 2;
       
    97     DPRINTF("write reg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->regs[saddr], val);
       
    98     switch (saddr) {
       
    99     case 1:
       
   100         DPRINTF("write dreg[%d]: 0x%2.2x -> 0x%2.2x\n", CS_RAP(s),
       
   101                 s->dregs[CS_RAP(s)], val);
       
   102         switch(CS_RAP(s)) {
       
   103         case 11:
       
   104         case 25: // Read only
       
   105             break;
       
   106         case 12:
       
   107             val &= 0x40;
       
   108             val |= CS_CDC_VER; // Codec version
       
   109             s->dregs[CS_RAP(s)] = val;
       
   110             break;
       
   111         default:
       
   112             s->dregs[CS_RAP(s)] = val;
       
   113             break;
       
   114         }
       
   115         break;
       
   116     case 2: // Read only
       
   117         break;
       
   118     case 4:
       
   119         if (val & 1)
       
   120             cs_reset(s);
       
   121         val &= 0x7f;
       
   122         s->regs[saddr] = val;
       
   123         break;
       
   124     default:
       
   125         s->regs[saddr] = val;
       
   126         break;
       
   127     }
       
   128 }
       
   129 
       
   130 static CPUReadMemoryFunc *cs_mem_read[3] = {
       
   131     cs_mem_readl,
       
   132     cs_mem_readl,
       
   133     cs_mem_readl,
       
   134 };
       
   135 
       
   136 static CPUWriteMemoryFunc *cs_mem_write[3] = {
       
   137     cs_mem_writel,
       
   138     cs_mem_writel,
       
   139     cs_mem_writel,
       
   140 };
       
   141 
       
   142 static void cs_save(QEMUFile *f, void *opaque)
       
   143 {
       
   144     CSState *s = opaque;
       
   145     unsigned int i;
       
   146 
       
   147     for (i = 0; i < CS_REGS; i++)
       
   148         qemu_put_be32s(f, &s->regs[i]);
       
   149 
       
   150     qemu_put_buffer(f, s->dregs, CS_DREGS);
       
   151 }
       
   152 
       
   153 static int cs_load(QEMUFile *f, void *opaque, int version_id)
       
   154 {
       
   155     CSState *s = opaque;
       
   156     unsigned int i;
       
   157 
       
   158     if (version_id > 1)
       
   159         return -EINVAL;
       
   160 
       
   161     for (i = 0; i < CS_REGS; i++)
       
   162         qemu_get_be32s(f, &s->regs[i]);
       
   163 
       
   164     qemu_get_buffer(f, s->dregs, CS_DREGS);
       
   165     return 0;
       
   166 }
       
   167 
       
   168 void cs_init(target_phys_addr_t base, int irq, void *intctl)
       
   169 {
       
   170     int cs_io_memory;
       
   171     CSState *s;
       
   172 
       
   173     s = qemu_mallocz(sizeof(CSState));
       
   174     if (!s)
       
   175         return;
       
   176 
       
   177     cs_io_memory = cpu_register_io_memory(0, cs_mem_read, cs_mem_write, s);
       
   178     cpu_register_physical_memory(base, CS_SIZE, cs_io_memory);
       
   179     register_savevm("cs4231", base, 1, cs_save, cs_load, s);
       
   180     qemu_register_reset(cs_reset, s);
       
   181     cs_reset(s);
       
   182 }