summaryrefslogtreecommitdiff
path: root/drivers/video/imx/hdp/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/imx/hdp/util.c')
-rw-r--r--drivers/video/imx/hdp/util.c329
1 files changed, 329 insertions, 0 deletions
diff --git a/drivers/video/imx/hdp/util.c b/drivers/video/imx/hdp/util.c
new file mode 100644
index 0000000000..727946a796
--- /dev/null
+++ b/drivers/video/imx/hdp/util.c
@@ -0,0 +1,329 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2016-2017 Cadence Design Systems, Inc.
+ * All rights reserved worldwide.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS",
+ * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright 2017 NXP
+ *
+ ******************************************************************************
+ *
+ * util.c
+ *
+ ******************************************************************************
+ */
+
+#include "util.h"
+#include "API_General.h"
+#include "externs.h"
+#ifndef __UBOOT__
+#include <string.h>
+#endif
+#include "apb_cfg.h"
+#include "opcodes.h"
+#ifndef __UBOOT__
+#include <stdio.h>
+
+#endif
+state_struct state;
+
+int cdn_bus_read(unsigned int addr, unsigned int *value)
+{
+ return state.bus_type ?
+ cdn_sapb_read(addr, value) : cdn_apb_read(addr, value);
+}
+
+int cdn_bus_write(unsigned int addr, unsigned int value)
+{
+ return state.bus_type ?
+ cdn_sapb_write(addr, value) : cdn_apb_write(addr, value);
+}
+
+void internal_itobe(int val, volatile unsigned char *dest, int bytes)
+{
+ int i;
+ for (i = bytes - 1; i >= 0; --i) {
+ dest[i] = (unsigned char)val;
+ val >>= 8;
+ }
+}
+
+uint32_t internal_betoi(volatile uint8_t const *src, uint8_t bytes)
+{
+ uint32_t ret = 0;
+ int i;
+
+ if (bytes > sizeof(ret)) {
+ printf("Warning. Read request for payload larger then supported.\n");
+ bytes = sizeof(ret);
+ }
+
+ for (i = 0; i < bytes; ++i) {
+ ret <<= 8;
+ ret |= (unsigned int)src[i];
+ }
+
+ return ret;
+}
+
+unsigned int internal_mkmsg(volatile unsigned char *dest, int valno, ...)
+{
+ va_list vl;
+ unsigned int len = 0;
+ va_start(vl, valno);
+ len = internal_vmkmsg(dest, valno, vl);
+ va_end(vl);
+ return len;
+}
+
+unsigned int internal_vmkmsg(volatile unsigned char *dest, int valno,
+ va_list vl)
+{
+ unsigned int len = 0;
+ int i;
+ for (i = 0; i < valno; ++i) {
+ int size = va_arg(vl, int);
+ if (size > 0) {
+ internal_itobe(va_arg(vl, int), dest, size);
+ dest += size;
+ len += size;
+ } else {
+ memcpy((void *)dest, va_arg(vl, void *), -size);
+ dest -= size;
+ len -= size;
+ }
+ }
+ return len;
+}
+
+void internal_tx_mkfullmsg(unsigned char module, unsigned char opcode,
+ int valno, ...)
+{
+ va_list vl;
+ va_start(vl, valno);
+ internal_vtx_mkfullmsg(module, opcode, valno, vl);
+ va_end(vl);
+}
+
+void internal_vtx_mkfullmsg(unsigned char module, unsigned char opcode,
+ int valno, va_list vl)
+{
+ unsigned int len =
+ internal_vmkmsg(state.txbuffer + INTERNAL_CMD_HEAD_SIZE, valno, vl);
+ internal_mbox_tx_enable(module, opcode, len);
+ state.txenable = 1;
+ state.running = 1;
+}
+
+void internal_readmsg(int valno, ...)
+{
+ va_list vl;
+ va_start(vl, valno);
+ internal_vreadmsg(valno, vl);
+ va_end(vl);
+}
+
+void internal_vreadmsg(int valno, va_list vl)
+{
+ uint8_t *src = state.rxbuffer + INTERNAL_CMD_HEAD_SIZE;
+ size_t i;
+
+ for (i = 0; i < (size_t) valno; ++i) {
+ int size = va_arg(vl, int);
+ void *ptr = va_arg(vl, void *);
+
+ if (!ptr) {
+ src += size;
+ } else if (!size) {
+ *((unsigned char **)ptr) = src;
+ } else if (size > 0) {
+ switch ((size_t) size) {
+ case sizeof(uint8_t):
+ *((uint8_t *)ptr) = internal_betoi(src, size);
+ break;
+ case sizeof(uint16_t):
+ *((uint16_t *)ptr) = internal_betoi(src, size);
+ break;
+ case 3: /* 3-byte value (e.g. DPCD address)
+ can be safely converted from BE.*/
+ case sizeof(uint32_t):
+ *((uint32_t *)ptr) = internal_betoi(src, size);
+ break;
+ default:
+ printf("Warning. Unsupported variable size.\n");
+ memcpy(ptr, src, size);
+ };
+
+ src += size;
+ } else {
+ memcpy(ptr, src, -size);
+ src -= size;
+ }
+ }
+}
+
+INTERNAL_MBOX_STATUS mailbox_write(unsigned char val)
+{
+ INTERNAL_MBOX_STATUS ret;
+ unsigned int full;
+ if (cdn_bus_read(MAILBOX_FULL_ADDR << 2, &full)) {
+ ret.tx_status = CDN_TX_APB_ERROR;
+ return ret;
+ }
+ if (full) {
+ ret.tx_status = CDN_TX_FULL;
+ return ret;
+ }
+ if (cdn_bus_write(MAILBOX0_WR_DATA << 2, val)) {
+ ret.tx_status = CDN_TX_APB_ERROR;
+ return ret;
+ }
+ ret.tx_status = CDN_TX_WRITE;
+ return ret;
+}
+
+INTERNAL_MBOX_STATUS mailbox_read(volatile unsigned char *val)
+{
+ INTERNAL_MBOX_STATUS ret;
+ unsigned int empty;
+ unsigned int rd;
+ if (cdn_bus_read(MAILBOX_EMPTY_ADDR << 2, &empty)) {
+ ret.rx_status = CDN_RX_APB_ERROR;
+ return ret;
+ }
+ if (empty) {
+ ret.rx_status = CDN_RX_EMPTY;
+ return ret;
+ }
+ if (cdn_bus_read(MAILBOX0_RD_DATA << 2, &rd)) {
+ ret.rx_status = CDN_RX_APB_ERROR;
+ return ret;
+ }
+ *val = (unsigned char)rd;
+ ret.rx_status = CDN_RX_READ;
+ return ret;
+}
+
+INTERNAL_MBOX_STATUS internal_mbox_tx_process(void)
+{
+ unsigned int txcount = 0;
+ unsigned int length =
+ (unsigned int)state.txbuffer[2] << 8 | (unsigned int)state.
+ txbuffer[3];
+ INTERNAL_MBOX_STATUS ret = {.txend = 0 };
+ ret.tx_status = CDN_TX_NOTHING;
+ INTERNAL_MBOX_STATUS tx_ret;
+ if (!state.txenable)
+ return ret;
+ while ((tx_ret.tx_status =
+ mailbox_write(state.txbuffer[state.txi]).tx_status) ==
+ CDN_TX_WRITE) {
+ txcount++;
+ if (++state.txi >= length + 4) {
+ state.txenable = 0;
+ state.txi = 0;
+ ret.txend = 1;
+ break;
+ }
+ }
+ if (txcount && tx_ret.tx_status == CDN_TX_FULL)
+ ret.tx_status = CDN_TX_WRITE;
+ else
+ ret.tx_status = tx_ret.tx_status;
+ return ret;
+}
+
+INTERNAL_MBOX_STATUS internal_mbox_rx_process(void)
+{
+ unsigned int rxcount = 0;
+ INTERNAL_MBOX_STATUS ret = { 0, 0, 0, 0 };
+ INTERNAL_MBOX_STATUS rx_ret;
+ while ((rx_ret.rx_status =
+ mailbox_read(state.rxbuffer + state.rxi).rx_status) ==
+ CDN_RX_READ) {
+ rxcount++;
+ if (++state.rxi >= 4 +
+ ((unsigned int)state.rxbuffer[2] << 8 |
+ (unsigned int)state.rxbuffer[3])) { /* end of message */
+ state.rxi = 0;
+ ret.rxend = 1;
+ state.rxenable = 0;
+ break;
+ }
+ }
+ ret.rx_status = rxcount ? CDN_RX_READ : CDN_RX_EMPTY;
+ return ret;
+}
+
+unsigned int internal_apb_available(void)
+{
+ return !(state.rxenable || state.txenable);
+}
+
+void internal_mbox_tx_enable(unsigned char module, unsigned char opcode,
+ unsigned short length)
+{
+ state.txbuffer[0] = opcode;
+ state.txbuffer[1] = module;
+ state.txbuffer[2] = (unsigned char)(length >> 8);
+ state.txbuffer[3] = (unsigned char)length;
+ state.txenable = 1;
+}
+
+CDN_API_STATUS internal_test_rx_head(unsigned char module, unsigned char opcode)
+{
+ if (opcode != state.rxbuffer[0])
+ return CDN_BAD_OPCODE;
+ if (module != state.rxbuffer[1])
+ return CDN_BAD_MODULE;
+ return CDN_OK;
+}
+
+CDN_API_STATUS internal_test_rx_head_match(void)
+{
+ return internal_test_rx_head(state.txbuffer[1], state.txbuffer[0]);
+}
+
+void print_fw_ver(void)
+{
+ unsigned short ver, verlib;
+ cdn_api_general_getcurversion(&ver, &verlib);
+ printf("FIRMWARE VERSION: %d, LIB VERSION: %d\n", ver, verlib);
+}
+
+unsigned short internal_get_msg_len(void)
+{
+ return ((unsigned short)state.rxbuffer[2] << 8) | (unsigned short)state.
+ rxbuffer[3];
+}