Moved to 48khz sample rate

Change-Id: Ic163aa2158a878453eceb45e13623a2deff44740
diff --git a/system/dev/audio/gauss-tdm/gauss-tdm-stream.cpp b/system/dev/audio/gauss-tdm/gauss-tdm-stream.cpp
index 486c76e..9d37bcb 100644
--- a/system/dev/audio/gauss-tdm/gauss-tdm-stream.cpp
+++ b/system/dev/audio/gauss-tdm/gauss-tdm-stream.cpp
@@ -539,7 +539,7 @@
     // enable mclk c, select fclk_div4 as source, divide by 20 to get 12.5MHz
     //  at 256 sclk/frame, this yields 48.828125kHz
     // TODO(hollande) - switch to pll to get accurate timing for 48kHz
-    regs_->mclk_ctl[MCLK_C] = (1 << 31) | (6 << 24) | (19);
+    regs_->mclk_ctl[MCLK_C] = (1 << 31) | (2 << 24) | (9);
 
     // configure mst_sclk_gen
     regs_->sclk_ctl[MCLK_C].ctl0 = (0x03 << 30) | (1 << 20) | (0 << 10) | 255;
diff --git a/system/dev/board/gauss/gauss.c b/system/dev/board/gauss/gauss.c
index e7c7b3c..fa5e3e0 100644
--- a/system/dev/board/gauss/gauss.c
+++ b/system/dev/board/gauss/gauss.c
@@ -147,6 +147,18 @@
         goto fail;
     }
 
+    status = a113_clk_init(&bus->clocks, bus->a113);
+    if (status != ZX_OK) {
+        zxlogf(ERROR, "a113_clk_init failed: %d\n",status);
+        goto fail;
+    }
+
+    printf("HHI_MPLL_CNTL9 = %08x\n",a113_clk_get_reg(bus->clocks,0xa8));
+    printf("HHI_MPLL_TOP_MISC = %08x\n",a113_clk_get_reg(bus->clocks,0xba));
+    a113_clk_set_mpll2(bus->clocks, 48000*256*20);
+    printf("HHI_MPLL_CNTL9 = %08x\n",a113_clk_get_reg(bus->clocks,0xa8));
+    printf("HHI_MPLL_TOP_MISC = %08x\n",a113_clk_get_reg(bus->clocks,0xba));
+
     bus->usb_mode_switch.ops = &usb_mode_switch_ops;
     bus->usb_mode_switch.ctx = bus;
 
diff --git a/system/dev/board/gauss/gauss.h b/system/dev/board/gauss/gauss.h
index fa591fa..1a6095a 100644
--- a/system/dev/board/gauss/gauss.h
+++ b/system/dev/board/gauss/gauss.h
@@ -8,12 +8,15 @@
 #include <ddk/protocol/platform-bus.h>
 #include <ddk/protocol/usb-mode-switch.h>
 #include <soc/aml-a113/a113-bus.h>
+#include <soc/aml-a113/a113-clocks.h>
+
 
 typedef struct {
     platform_bus_protocol_t pbus;
     a113_bus_t* a113;
     usb_mode_switch_protocol_t usb_mode_switch;
     io_buffer_t usb_phy;
+    a113_clk_dev_t *clocks;
 } gauss_bus_t;
 
 // gauss-audio.c
diff --git a/system/dev/soc/aml-a113/a113-clocks.c b/system/dev/soc/aml-a113/a113-clocks.c
new file mode 100644
index 0000000..566f195
--- /dev/null
+++ b/system/dev/soc/aml-a113/a113-clocks.c
@@ -0,0 +1,85 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+#include <threads.h>
+#include <unistd.h>
+
+
+#include <bits/limits.h>
+#include <ddk/debug.h>
+#include <hw/reg.h>
+
+#include <zircon/assert.h>
+#include <zircon/types.h>
+
+#include <soc/aml-a113/a113-clocks.h>
+
+
+#define SDM_FRACTIONALITY 16384
+#define A113_FIXED_PLL_RATE 2000000000
+
+#define DIV_ROUND_UP(n,d) ((n + d - 1) / d)
+/* create instance of a113_clock_t and do basic initialization.
+*/
+zx_status_t a113_clk_init(a113_clk_dev_t **device, a113_bus_t *host_bus) {
+
+    *device = calloc(1, sizeof(a113_clk_dev_t));
+    if (!(*device)) {
+        return ZX_ERR_NO_MEMORY;
+    }
+
+    (*device)->host_bus = host_bus;  // TODO - might not need this
+
+    zx_handle_t resource = get_root_resource();
+    zx_status_t status;
+
+    status = io_buffer_init_physical(&(*device)->regs_iobuff, A113_CLOCKS_BASE_PHYS,
+                                     PAGE_SIZE, resource, ZX_CACHE_POLICY_UNCACHED_DEVICE);
+
+    if (status != ZX_OK) {
+        zxlogf(ERROR, "a113_clk_init: io_buffer_init_physical failed %d\n", status);
+        goto init_fail;
+    }
+
+    (*device)->virt_regs = (zx_vaddr_t)(io_buffer_virt(&(*device)->regs_iobuff));
+
+    return ZX_OK;
+
+init_fail:
+    if (*device) {
+        io_buffer_release(&(*device)->regs_iobuff);
+        free(*device);
+     };
+    return status;
+}
+
+static void a113_clk_update_reg(a113_clk_dev_t *dev, uint32_t offset,
+                                                     uint32_t pos,
+                                                     uint32_t bits,
+                                                     uint32_t value) {
+    uint32_t reg = a113_clk_get_reg(dev,offset);
+    reg &= ~(((1 << bits) - 1) << pos);
+    reg |=  (value & ((1 << bits) - 1)) << pos;
+    a113_clk_set_reg(dev,offset,reg);
+}
+
+zx_status_t a113_clk_set_mpll2(a113_clk_dev_t *device, uint64_t rate) {
+
+    uint64_t n = A113_FIXED_PLL_RATE/rate;  //calculate the integer ratio;
+    printf("Integer divider = %ld\n",n);
+
+    uint64_t sdm = DIV_ROUND_UP((A113_FIXED_PLL_RATE - n * rate) * SDM_FRACTIONALITY, rate);
+    printf("Fractional divider = %ld\n",sdm);
+
+    a113_clk_update_reg(device, 0xa8, 0, 14, (uint32_t)sdm);
+    a113_clk_update_reg(device, 0xa8, 16, 9, (uint32_t)n);
+    a113_clk_update_reg(device, 0xa8, 15, 1, 1);
+    a113_clk_update_reg(device, 0xa8, 14, 1, 1);
+
+    a113_clk_update_reg(device, 0xba, 2, 1, 1);
+
+
+    return ZX_OK;
+}
diff --git a/system/dev/soc/aml-a113/include/soc/aml-a113/a113-clocks.h b/system/dev/soc/aml-a113/include/soc/aml-a113/a113-clocks.h
new file mode 100644
index 0000000..b352ca4
--- /dev/null
+++ b/system/dev/soc/aml-a113/include/soc/aml-a113/a113-clocks.h
@@ -0,0 +1,31 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <ddk/io-buffer.h>
+#include <ddk/protocol/platform-bus.h>
+
+#include "a113-bus.h"
+
+#define A113_CLOCKS_BASE_PHYS 0xff63c000
+
+typedef struct {
+    a113_bus_t      *host_bus;
+    io_buffer_t     regs_iobuff;
+    zx_vaddr_t      virt_regs;
+} a113_clk_dev_t;
+
+
+static inline uint32_t a113_clk_get_reg(a113_clk_dev_t *dev, uint32_t offset) {
+    return   ((uint32_t *)dev->virt_regs)[offset];
+}
+
+static inline uint32_t a113_clk_set_reg(a113_clk_dev_t *dev, uint32_t offset, uint32_t value) {
+    ((uint32_t *)dev->virt_regs)[offset] = value;
+    return   ((uint32_t *)dev->virt_regs)[offset];
+}
+
+zx_status_t a113_clk_init(a113_clk_dev_t **device, a113_bus_t *host_bus);
+zx_status_t a113_clk_set_mpll2(a113_clk_dev_t *device, uint64_t rate);
diff --git a/system/dev/soc/aml-a113/rules.mk b/system/dev/soc/aml-a113/rules.mk
index 564a45b..4bde6d4 100644
--- a/system/dev/soc/aml-a113/rules.mk
+++ b/system/dev/soc/aml-a113/rules.mk
@@ -9,6 +9,7 @@
 MODULE_TYPE := userlib
 
 MODULE_SRCS += \
+	$(LOCAL_DIR)/a113-clocks.c \
     $(LOCAL_DIR)/a113-gpio.c \
     $(LOCAL_DIR)/a113-i2c.c \
     $(LOCAL_DIR)/aml-i2c.c \