summaryrefslogtreecommitdiff
path: root/drivers/mxc/hdp/util.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mxc/hdp/util.h')
-rw-r--r--drivers/mxc/hdp/util.h394
1 files changed, 394 insertions, 0 deletions
diff --git a/drivers/mxc/hdp/util.h b/drivers/mxc/hdp/util.h
new file mode 100644
index 000000000000..5cf3c815a059
--- /dev/null
+++ b/drivers/mxc/hdp/util.h
@@ -0,0 +1,394 @@
+/******************************************************************************
+ *
+ * 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-2018 NXP
+ *
+ ******************************************************************************
+ *
+ * util.h
+ *
+ ******************************************************************************
+ */
+
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_edid.h>
+
+/**
+ * \addtogroup GENERAL_API
+ * \{
+ */
+/** status code returned by API calls */
+typedef enum {
+ /** operation succedded */
+ CDN_OK = 0,
+ /** CEC operation succedded */
+ CDN_CEC_ERR_NONE = 0,
+ /** mailbox is currently sending or receiving data */
+ CDN_BSY,
+ /** message set up and ready to be sent, no data sent yet */
+ CDN_STARTED,
+ /** error encountered while reading/writing APB */
+ CDN_ERR,
+ /** reply returned with bad opcode */
+ CDN_BAD_OPCODE,
+ /** reply returned with bad module */
+ CDN_BAD_MODULE,
+ /** reply not supported mode */
+ CDN_ERROR_NOT_SUPPORTED,
+ /** Invalid argument passed to CEC API function */
+ CDN_CEC_ERR_INVALID_ARG,
+ /**
+ * TX Buffer for CEC Messages is full. This is applicable only
+ * when TX Buffers for CEC Messages are implemented in the HW.
+ */
+ CDN_CEC_ERR_TX_BUFF_FULL,
+ /** No Messages in the RX Buffers are present. */
+ CDN_CEC_ERR_RX_BUFF_EMPTY,
+ /** Timeout during TX operation */
+ CDN_CEC_ERR_TX_TIMEOUT,
+ /** Timeout during RX operation */
+ CDN_CEC_ERR_RX_TIMEOUT,
+ /** Data transmision fail. */
+ CDN_CEC_ERR_TX_FAILED,
+ /** Data reception fail. */
+ CDN_CEC_ERR_RX_FAILED,
+ /** Operation aborted. */
+ CDN_CEC_ERR_ABORT,
+ /** All Logical Addresses are in use. */
+ CDN_CEC_ERR_ALL_LA_IN_USE,
+} CDN_API_STATUS;
+
+typedef enum {
+ CDN_DPTX,
+ CDN_HDMITX_TYPHOON,
+ CDN_HDMITX_KIRAN,
+} CDN_PROTOCOL_TYPE;
+
+typedef enum {
+ CDN_BUS_TYPE_APB = 0,
+ CDN_BUS_TYPE_SAPB = 1
+} CDN_BUS_TYPE;
+
+typedef enum {
+ NUM_OF_LANES_1 = 1,
+ NUM_OF_LANES_2 = 2,
+ NUM_OF_LANES_4 = 4,
+} VIC_NUM_OF_LANES;
+
+typedef enum {
+ RATE_1_6 = 162,
+ RATE_2_1 = 216,
+ RATE_2_4 = 243,
+ RATE_2_7 = 270,
+ RATE_3_2 = 324,
+ RATE_4_3 = 432,
+ RATE_5_4 = 540,
+ RATE_8_1 = 810,
+} VIC_SYMBOL_RATE;
+
+typedef enum {
+ PXL_RGB = 0x1,
+ YCBCR_4_4_4 = 0x2,
+ YCBCR_4_2_2 = 0x4,
+ YCBCR_4_2_0 = 0x8,
+ Y_ONLY = 0x10,
+} VIC_PXL_ENCODING_FORMAT;
+
+typedef enum {
+ BCS_6 = 0x1,
+ BCS_8 = 0x2,
+ BCS_10 = 0x4,
+ BCS_12 = 0x8,
+ BCS_16 = 0x10,
+} VIC_COLOR_DEPTH;
+
+typedef enum {
+ STEREO_VIDEO_LEFT = 0x0,
+ STEREO_VIDEO_RIGHT = 0x1,
+} STEREO_VIDEO_ATTR;
+
+typedef enum {
+ BT_601 = 0x0,
+ BT_709 = 0x1,
+} BT_TYPE;
+
+typedef struct {
+ /** apb write status */
+ enum tx_status_enum {
+ /** one or more bytes written */
+ CDN_TX_WRITE = 0,
+ /** nothing to write */
+ CDN_TX_NOTHING = 1,
+ /** mailbox full, 0 bytes written */
+ CDN_TX_FULL = 2,
+ /** APB error while writing */
+ CDN_TX_APB_ERROR = 3
+ } tx_status:3;
+ /** apb read status */
+ enum rx_status_enum {
+ /** 1 or more bytes read */
+ CDN_RX_READ = 0,
+ /** mailbox empty, 0 bytes read */
+ CDN_RX_EMPTY = 1,
+ /** apb error while reading */
+ CDN_RX_APB_ERROR = 2
+ } rx_status:2;
+ /** indicates end of currenly recived message */
+ u8 rxend:1;
+ /** end of tx message reached */
+ u8 txend:1;
+} INTERNAL_MBOX_STATUS;
+
+struct hdp_mem {
+ void __iomem *regs_base; /* Controller regs base */
+ void __iomem *ss_base; /* HDP Subsystem regs base */
+ void __iomem *rst_base; /* HDP Subsystem reset base */
+};
+
+struct hdp_rw_func {
+ int (*read_reg) (struct hdp_mem *mem, u32 addr, u32 *value);
+ int (*write_reg) (struct hdp_mem *mem, u32 addr, u32 value);
+ int (*sread_reg) (struct hdp_mem *mem, u32 addr, u32 *value);
+ int (*swrite_reg) (struct hdp_mem *mem, u32 addr, u32 value);
+};
+
+typedef struct {
+ u8 txBuffer[1024];
+ u8 rxBuffer[1024];
+ u32 txi; //iterators
+ u32 rxi;
+ u8 txEnable; //data readt to send
+ u8 rxEnable;
+ u8 running;
+ CDN_BUS_TYPE bus_type;
+ u32 tmp;
+ u32 edp; /* use eDP */
+
+ struct mutex mutex; //mutex may replace running
+ struct hdp_mem *mem;
+ struct hdp_rw_func *rw;
+} state_struct;
+/**
+ * \addtogroup UTILS
+ * \{
+ */
+#define INTERNAL_CMD_HEAD_SIZE 4
+
+/**
+ * \brief expands to blocking function body
+ * \param x - function call
+ */
+#define MAILBOX_FILL_TIMEOUT 1500
+#define internal_block_function(y, x) \
+do { \
+ unsigned long end_jiffies = jiffies + \
+ msecs_to_jiffies(MAILBOX_FILL_TIMEOUT); \
+ CDN_API_STATUS ret; \
+ mutex_lock(y); \
+ do { \
+ ret = x; \
+ cpu_relax(); \
+ } while (time_after(end_jiffies, jiffies) && \
+ (ret == CDN_BSY || ret == CDN_STARTED)); \
+ mutex_unlock(y); \
+ return ret; \
+} while (0)
+
+/**
+ * \brief write message and write response (if any), non-blocking way. Also sets state.running = 0
+ */
+#define internal_process_messages(state) \
+do { \
+ if (state->txEnable && !internal_mbox_tx_process(state).txend) \
+ return CDN_BSY; \
+ if (state->rxEnable && !internal_mbox_rx_process(state).rxend) \
+ return CDN_BSY; \
+ state->running = 0; \
+} while (0)
+
+#define internal_opcode_ok_or_return(state, module, opcode) do { \
+ CDN_API_STATUS ret; \
+ ret = internal_test_rx_head(state, module, opcode); \
+ if (ret != CDN_OK) \
+ return ret; \
+} while (0)
+
+#define internal_opcode_match_or_return(state) do { \
+ CDN_API_STATUS ret; \
+ ret = internal_test_rx_head_match(state); \
+ if (ret != CDN_OK) \
+ return ret; \
+} while (0)
+
+/* macro for simple tx only command, command format as in mkfullmsg (with count) */
+#define internal_macro_command_tx(state, module, opcode, bustype, command...) \
+do { \
+ if (!state->running) { \
+ internal_tx_mkfullmsg(state, module, opcode, command); \
+ state->bus_type = bustype; \
+ return CDN_STARTED; \
+ } \
+ internal_process_messages(state); \
+} while (0)
+
+/* macro for command with response with matching opcode, command format as in mkfullmsg (with count) */
+#define internal_macro_command_txrx(state, module, opcode, bustype, command...) \
+do { \
+ if (!state->running) { \
+ internal_tx_mkfullmsg(state, module, opcode, command); \
+ state->bus_type = bustype; \
+ state->rxEnable = 1; \
+ return CDN_STARTED; \
+ } \
+ internal_process_messages(state); \
+ internal_opcode_match_or_return(state); \
+} while (0)
+
+/**
+ * \brief put val into dest in big endian format
+ * \param val - value to put
+ * \param dest - place to put value
+ * \param bytes - true size of val in bytes. for example if bytes = 2 val is treated as short int
+ */
+void internal_itobe(int val, volatile u8 *dest, int bytes);
+
+/**
+ * \brief read big endian value from src and return it
+ * \param src - source to read from
+ * \param bytes - size of read value
+ * \return result
+ */
+u32 internal_betoi(volatile u8 const *src, u8 bytes);
+
+/**
+ * \brief create message from size and value pairs; also sets state.runnging and state.txEnable
+ * \param dest - pointer to write message to
+ * \param valNo - number of values to write
+ * \param ... - pairs of size and value, each value is written after another. if size is positive value, value is written with #internal_itobe, if size is negative, value is treated as src pointer for memcpy
+ *
+ * example:
+ *
+ * u16 x = 0xAABB;
+ *
+ * internal_mkmsg(dest, 3, 1, 1, 2, 3, -2, &x);
+ *
+ * will write 01 00 03 AA BB to dest
+ */
+u32 internal_mkmsg(volatile u8 *dest, int valNo, ...);
+u32 internal_vmkmsg(volatile u8 *dest, int valNo, va_list vl);
+
+/**
+ * \brief setup message header in txBuffer, set txEnable = 1
+ */
+void internal_mbox_tx_enable(state_struct *state, u8 module, u8 opcode,
+ u16 length);
+
+/**
+ * \brief write from txBuffer to mailbox untill full or end of message.
+ *
+ * when txEnable == 0 writes nothing
+ * when write reaches end of message set txEnable = 0
+ */
+
+/**
+ * \brief combination of #internal_mkmsg and #internal_mbox_tx_enable
+ *
+ * #internal_mkmsg dest and #internal_mbox_tx_enable length are determined automaticly
+ * this function also sets state.txEnable = 1 and state.running
+ */
+void internal_tx_mkfullmsg(state_struct *state, u8 module, u8 opcode,
+ int valNo, ...);
+void internal_vtx_mkfullmsg(state_struct *state, u8 module, u8 opcode,
+ int valNo, va_list vl);
+
+/**
+ * \brief read from state.txBuffer and store results in specified pointers
+ * \param valNo - numbero of values to read
+ * \param ... - pairs of size and ptr
+ *
+ * this function is similar to #internal_mkmsg -
+ *
+ * when size is positive read value using #internal_betoi
+ * when size is negative mempcy from txBuffer to ptr -size bytes
+ * when size is 0 write to ptr addres of current position in rxbuffer
+ * when ptr is NULL ignore size bytes (if size is negative this will rewind buffer)
+ */
+void internal_readmsg(state_struct *state, int valNo, ...);
+void internal_vreadmsg(state_struct *state, int valNo, va_list vl);
+
+INTERNAL_MBOX_STATUS internal_mbox_tx_process(state_struct *state);
+/**
+ * \brief read to rxBuffer from mailbox untill empty or end of message
+ *
+ * when rxEnable == 0 reads nothing
+ * when end of message reached sets rxEnable = 0
+ */
+INTERNAL_MBOX_STATUS internal_mbox_rx_process(state_struct *state);
+
+/**
+ * \brief check if apb is available
+ * \return !(rxEnable && txEable)
+ */
+u32 internal_apb_available(state_struct *state);
+
+/**
+ * \brief test if parameters match module and opcode in rxBuffer
+ * \return CDN_OK or CDN_BAD_OPCODE or CDN_BAD_MODULE
+ */
+CDN_API_STATUS internal_test_rx_head(state_struct *state, u8 module,
+ u8 opcode);
+
+CDN_API_STATUS internal_test_rx_head_match(state_struct *state);
+
+/**
+ * \brief print current fw and lib version
+ */
+void print_fw_ver(state_struct *state);
+
+int cdn_apb_read(state_struct *state, u32 addr, u32 *value);
+int cdn_sapb_read(state_struct *state, u32 addr, u32 *value);
+int cdn_apb_write(state_struct *state, u32 addr, u32 value);
+int cdn_sapb_write(state_struct *state, u32 addr, u32 value);
+void cdn_sleep(u32 ms);
+void cdn_usleep(u32 us);
+u16 internal_get_msg_len(state_struct *state);
+#endif