diff options
Diffstat (limited to 'drivers/mxc/hdp/util.h')
-rw-r--r-- | drivers/mxc/hdp/util.h | 394 |
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 |