8288 lines
256 KiB
Diff
8288 lines
256 KiB
Diff
|
Broadcom Crystal HD video decoder driver from upstream staging/linux-next.
|
||
|
|
||
|
Signed-off-by: Jarod Wilson <jarod@redhat.com>
|
||
|
|
||
|
---
|
||
|
drivers/staging/Kconfig | 2 +
|
||
|
drivers/staging/Makefile | 1 +
|
||
|
drivers/staging/crystalhd/Kconfig | 6 +
|
||
|
drivers/staging/crystalhd/Makefile | 6 +
|
||
|
drivers/staging/crystalhd/TODO | 16 +
|
||
|
drivers/staging/crystalhd/bc_dts_defs.h | 498 ++++++
|
||
|
drivers/staging/crystalhd/bc_dts_glob_lnx.h | 299 ++++
|
||
|
drivers/staging/crystalhd/bc_dts_types.h | 121 ++
|
||
|
drivers/staging/crystalhd/bcm_70012_regs.h | 757 +++++++++
|
||
|
drivers/staging/crystalhd/crystalhd_cmds.c | 1058 ++++++++++++
|
||
|
drivers/staging/crystalhd/crystalhd_cmds.h | 88 +
|
||
|
drivers/staging/crystalhd/crystalhd_fw_if.h | 369 ++++
|
||
|
drivers/staging/crystalhd/crystalhd_hw.c | 2395 +++++++++++++++++++++++++++
|
||
|
drivers/staging/crystalhd/crystalhd_hw.h | 398 +++++
|
||
|
drivers/staging/crystalhd/crystalhd_lnx.c | 780 +++++++++
|
||
|
drivers/staging/crystalhd/crystalhd_lnx.h | 95 ++
|
||
|
drivers/staging/crystalhd/crystalhd_misc.c | 1029 ++++++++++++
|
||
|
drivers/staging/crystalhd/crystalhd_misc.h | 229 +++
|
||
|
18 files changed, 8147 insertions(+), 0 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
|
||
|
index 94eb863..61ec152 100644
|
||
|
--- a/drivers/staging/Kconfig
|
||
|
+++ b/drivers/staging/Kconfig
|
||
|
@@ -145,5 +145,7 @@ source "drivers/staging/netwave/Kconfig"
|
||
|
|
||
|
source "drivers/staging/iio/Kconfig"
|
||
|
|
||
|
+source "drivers/staging/crystalhd/Kconfig"
|
||
|
+
|
||
|
endif # !STAGING_EXCLUDE_BUILD
|
||
|
endif # STAGING
|
||
|
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
|
||
|
index b5e67b8..dc40493 100644
|
||
|
--- a/drivers/staging/Makefile
|
||
|
+++ b/drivers/staging/Makefile
|
||
|
@@ -53,3 +53,4 @@ obj-$(CONFIG_WAVELAN) += wavelan/
|
||
|
obj-$(CONFIG_RAR_REGISTER) += rar/
|
||
|
obj-$(CONFIG_DX_SEP) += sep/
|
||
|
obj-$(CONFIG_IIO) += iio/
|
||
|
+obj-$(CONFIG_CRYSTALHD) += crystalhd/
|
||
|
diff --git a/drivers/staging/crystalhd/Kconfig b/drivers/staging/crystalhd/Kconfig
|
||
|
new file mode 100644
|
||
|
index 0000000..56b414b
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/Kconfig
|
||
|
@@ -0,0 +1,6 @@
|
||
|
+config CRYSTALHD
|
||
|
+ tristate "Broadcom Crystal HD video decoder support"
|
||
|
+ depends on PCI
|
||
|
+ default n
|
||
|
+ help
|
||
|
+ Support for the Broadcom Crystal HD video decoder chipset
|
||
|
diff --git a/drivers/staging/crystalhd/Makefile b/drivers/staging/crystalhd/Makefile
|
||
|
new file mode 100644
|
||
|
index 0000000..e2af0ce
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/Makefile
|
||
|
@@ -0,0 +1,6 @@
|
||
|
+obj-$(CONFIG_CRYSTALHD) += crystalhd.o
|
||
|
+
|
||
|
+crystalhd-objs := crystalhd_cmds.o \
|
||
|
+ crystalhd_hw.o \
|
||
|
+ crystalhd_lnx.o \
|
||
|
+ crystalhd_misc.o
|
||
|
diff --git a/drivers/staging/crystalhd/TODO b/drivers/staging/crystalhd/TODO
|
||
|
new file mode 100644
|
||
|
index 0000000..69be5d0
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/TODO
|
||
|
@@ -0,0 +1,16 @@
|
||
|
+- Testing
|
||
|
+- Cleanup return codes
|
||
|
+- Cleanup typedefs
|
||
|
+- Cleanup all WIN* references
|
||
|
+- Allocate an Accelerator device class specific Major number,
|
||
|
+ since we don't have any other open sourced accelerators, it is the only
|
||
|
+ one in that category for now.
|
||
|
+ A somewhat similar device is the DXR2/3
|
||
|
+
|
||
|
+Please send patches to:
|
||
|
+Greg Kroah-Hartman <greg@kroah.com>
|
||
|
+Naren Sankar <nsankar@broadcom.com>
|
||
|
+Jarod Wilson <jarod@wilsonet.com>
|
||
|
+Scott Davilla <davilla@4pi.com>
|
||
|
+Manu Abraham <abraham.manu@gmail.com>
|
||
|
+
|
||
|
diff --git a/drivers/staging/crystalhd/bc_dts_defs.h b/drivers/staging/crystalhd/bc_dts_defs.h
|
||
|
new file mode 100644
|
||
|
index 0000000..c34cc07
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/bc_dts_defs.h
|
||
|
@@ -0,0 +1,498 @@
|
||
|
+/********************************************************************
|
||
|
+ * Copyright(c) 2006-2009 Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: bc_dts_defs.h
|
||
|
+ *
|
||
|
+ * Description: Common definitions for all components. Only types
|
||
|
+ * is allowed to be included from this file.
|
||
|
+ *
|
||
|
+ * AU
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ ********************************************************************
|
||
|
+ * This header is free software: you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU Lesser General Public License as published
|
||
|
+ * by the Free Software Foundation, either version 2.1 of the License.
|
||
|
+ *
|
||
|
+ * This header is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU Lesser General Public License for more details.
|
||
|
+ * You should have received a copy of the GNU Lesser General Public License
|
||
|
+ * along with this header. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ *******************************************************************/
|
||
|
+
|
||
|
+#ifndef _BC_DTS_DEFS_H_
|
||
|
+#define _BC_DTS_DEFS_H_
|
||
|
+
|
||
|
+#include "bc_dts_types.h"
|
||
|
+
|
||
|
+/* BIT Mask */
|
||
|
+#define BC_BIT(_x) (1 << (_x))
|
||
|
+
|
||
|
+typedef enum _BC_STATUS {
|
||
|
+ BC_STS_SUCCESS = 0,
|
||
|
+ BC_STS_INV_ARG = 1,
|
||
|
+ BC_STS_BUSY = 2,
|
||
|
+ BC_STS_NOT_IMPL = 3,
|
||
|
+ BC_STS_PGM_QUIT = 4,
|
||
|
+ BC_STS_NO_ACCESS = 5,
|
||
|
+ BC_STS_INSUFF_RES = 6,
|
||
|
+ BC_STS_IO_ERROR = 7,
|
||
|
+ BC_STS_NO_DATA = 8,
|
||
|
+ BC_STS_VER_MISMATCH = 9,
|
||
|
+ BC_STS_TIMEOUT = 10,
|
||
|
+ BC_STS_FW_CMD_ERR = 11,
|
||
|
+ BC_STS_DEC_NOT_OPEN = 12,
|
||
|
+ BC_STS_ERR_USAGE = 13,
|
||
|
+ BC_STS_IO_USER_ABORT = 14,
|
||
|
+ BC_STS_IO_XFR_ERROR = 15,
|
||
|
+ BC_STS_DEC_NOT_STARTED = 16,
|
||
|
+ BC_STS_FWHEX_NOT_FOUND = 17,
|
||
|
+ BC_STS_FMT_CHANGE = 18,
|
||
|
+ BC_STS_HIF_ACCESS = 19,
|
||
|
+ BC_STS_CMD_CANCELLED = 20,
|
||
|
+ BC_STS_FW_AUTH_FAILED = 21,
|
||
|
+ BC_STS_BOOTLOADER_FAILED = 22,
|
||
|
+ BC_STS_CERT_VERIFY_ERROR = 23,
|
||
|
+ BC_STS_DEC_EXIST_OPEN = 24,
|
||
|
+ BC_STS_PENDING = 25,
|
||
|
+ BC_STS_CLK_NOCHG = 26,
|
||
|
+
|
||
|
+ /* Must be the last one.*/
|
||
|
+ BC_STS_ERROR = -1
|
||
|
+} BC_STATUS;
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * Registry Key Definitions *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+#define BC_REG_KEY_MAIN_PATH "Software\\Broadcom\\MediaPC\\70010"
|
||
|
+#define BC_REG_KEY_FWPATH "FirmwareFilePath"
|
||
|
+#define BC_REG_KEY_SEC_OPT "DbgOptions"
|
||
|
+
|
||
|
+/*
|
||
|
+ * Options:
|
||
|
+ *
|
||
|
+ * b[5] = Enable RSA KEY in EEPROM Support
|
||
|
+ * b[6] = Enable Old PIB scheme. (0 = Use PIB with video scheme)
|
||
|
+ *
|
||
|
+ * b[12] = Enable send message to NotifyIcon
|
||
|
+ *
|
||
|
+ */
|
||
|
+
|
||
|
+typedef enum _BC_SW_OPTIONS {
|
||
|
+ BC_OPT_DOSER_OUT_ENCRYPT = BC_BIT(3),
|
||
|
+ BC_OPT_LINK_OUT_ENCRYPT = BC_BIT(29),
|
||
|
+} BC_SW_OPTIONS;
|
||
|
+
|
||
|
+typedef struct _BC_REG_CONFIG{
|
||
|
+ uint32_t DbgOptions;
|
||
|
+} BC_REG_CONFIG;
|
||
|
+
|
||
|
+#if defined(__KERNEL__) || defined(__LINUX_USER__)
|
||
|
+#else
|
||
|
+/* Align data structures */
|
||
|
+#define ALIGN(x) __declspec(align(x))
|
||
|
+#endif
|
||
|
+
|
||
|
+/* mode
|
||
|
+ * b[0]..b[7] = _DtsDeviceOpenMode
|
||
|
+ * b[8] = Load new FW
|
||
|
+ * b[9] = Load file play back FW
|
||
|
+ * b[10] = Disk format (0 for HD DVD and 1 for BLU ray)
|
||
|
+ * b[11]-b[15] = default output resolution
|
||
|
+ * b[16] = Skip TX CPB Buffer Check
|
||
|
+ * b[17] = Adaptive Output Encrypt/Scramble Scheme
|
||
|
+ * b[18]-b[31] = reserved for future use
|
||
|
+ */
|
||
|
+
|
||
|
+/* To allow multiple apps to open the device. */
|
||
|
+enum _DtsDeviceOpenMode {
|
||
|
+ DTS_PLAYBACK_MODE = 0,
|
||
|
+ DTS_DIAG_MODE,
|
||
|
+ DTS_MONITOR_MODE,
|
||
|
+ DTS_HWINIT_MODE
|
||
|
+};
|
||
|
+
|
||
|
+/* To enable the filter to selectively enable/disable fixes or erratas */
|
||
|
+enum _DtsDeviceFixMode {
|
||
|
+ DTS_LOAD_NEW_FW = BC_BIT(8),
|
||
|
+ DTS_LOAD_FILE_PLAY_FW = BC_BIT(9),
|
||
|
+ DTS_DISK_FMT_BD = BC_BIT(10),
|
||
|
+ /* b[11]-b[15] : Default output resolution */
|
||
|
+ DTS_SKIP_TX_CHK_CPB = BC_BIT(16),
|
||
|
+ DTS_ADAPTIVE_OUTPUT_PER = BC_BIT(17),
|
||
|
+ DTS_INTELLIMAP = BC_BIT(18),
|
||
|
+ /* b[19]-b[21] : select clock frequency */
|
||
|
+ DTS_PLAYBACK_DROP_RPT_MODE = BC_BIT(22)
|
||
|
+};
|
||
|
+
|
||
|
+#define DTS_DFLT_RESOLUTION(x) (x<<11)
|
||
|
+
|
||
|
+#define DTS_DFLT_CLOCK(x) (x<<19)
|
||
|
+
|
||
|
+/* F/W File Version corresponding to S/W Releases */
|
||
|
+enum _FW_FILE_VER {
|
||
|
+ /* S/W release: 02.04.02 F/W release 2.12.2.0 */
|
||
|
+ BC_FW_VER_020402 = ((12<<16) | (2<<8) | (0))
|
||
|
+};
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * Stream Types for DtsOpenDecoder() *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+enum _DtsOpenDecStreamTypes {
|
||
|
+ BC_STREAM_TYPE_ES = 0,
|
||
|
+ BC_STREAM_TYPE_PES = 1,
|
||
|
+ BC_STREAM_TYPE_TS = 2,
|
||
|
+ BC_STREAM_TYPE_ES_TSTAMP = 6,
|
||
|
+};
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * Video Algorithms for DtsSetVideoParams() *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+enum _DtsSetVideoParamsAlgo {
|
||
|
+ BC_VID_ALGO_H264 = 0,
|
||
|
+ BC_VID_ALGO_MPEG2 = 1,
|
||
|
+ BC_VID_ALGO_VC1 = 4,
|
||
|
+ BC_VID_ALGO_VC1MP = 7,
|
||
|
+};
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * MPEG Extension to the PPB *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+#define BC_MPEG_VALID_PANSCAN (1)
|
||
|
+
|
||
|
+typedef struct _BC_PIB_EXT_MPEG {
|
||
|
+ uint32_t valid;
|
||
|
+ /* Always valid, defaults to picture size if no
|
||
|
+ * sequence display extension in the stream. */
|
||
|
+ uint32_t display_horizontal_size;
|
||
|
+ uint32_t display_vertical_size;
|
||
|
+
|
||
|
+ /* MPEG_VALID_PANSCAN
|
||
|
+ * Offsets are a copy values from the MPEG stream. */
|
||
|
+ uint32_t offset_count;
|
||
|
+ int32_t horizontal_offset[3];
|
||
|
+ int32_t vertical_offset[3];
|
||
|
+
|
||
|
+} BC_PIB_EXT_MPEG;
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * H.264 Extension to the PPB *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+/* Bit definitions for 'other.h264.valid' field */
|
||
|
+#define H264_VALID_PANSCAN (1)
|
||
|
+#define H264_VALID_SPS_CROP (2)
|
||
|
+#define H264_VALID_VUI (4)
|
||
|
+
|
||
|
+typedef struct _BC_PIB_EXT_H264 {
|
||
|
+ /* 'valid' specifies which fields (or sets of
|
||
|
+ * fields) below are valid. If the corresponding
|
||
|
+ * bit in 'valid' is NOT set then that field(s)
|
||
|
+ * is (are) not initialized. */
|
||
|
+ uint32_t valid;
|
||
|
+
|
||
|
+ /* H264_VALID_PANSCAN */
|
||
|
+ uint32_t pan_scan_count;
|
||
|
+ int32_t pan_scan_left[3];
|
||
|
+ int32_t pan_scan_right[3];
|
||
|
+ int32_t pan_scan_top[3];
|
||
|
+ int32_t pan_scan_bottom[3];
|
||
|
+
|
||
|
+ /* H264_VALID_SPS_CROP */
|
||
|
+ int32_t sps_crop_left;
|
||
|
+ int32_t sps_crop_right;
|
||
|
+ int32_t sps_crop_top;
|
||
|
+ int32_t sps_crop_bottom;
|
||
|
+
|
||
|
+ /* H264_VALID_VUI */
|
||
|
+ uint32_t chroma_top;
|
||
|
+ uint32_t chroma_bottom;
|
||
|
+
|
||
|
+} BC_PIB_EXT_H264;
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * VC1 Extension to the PPB *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+#define VC1_VALID_PANSCAN (1)
|
||
|
+
|
||
|
+typedef struct _BC_PIB_EXT_VC1 {
|
||
|
+ uint32_t valid;
|
||
|
+
|
||
|
+ /* Always valid, defaults to picture size if no
|
||
|
+ * sequence display extension in the stream. */
|
||
|
+ uint32_t display_horizontal_size;
|
||
|
+ uint32_t display_vertical_size;
|
||
|
+
|
||
|
+ /* VC1 pan scan windows */
|
||
|
+ uint32_t num_panscan_windows;
|
||
|
+ int32_t ps_horiz_offset[4];
|
||
|
+ int32_t ps_vert_offset[4];
|
||
|
+ int32_t ps_width[4];
|
||
|
+ int32_t ps_height[4];
|
||
|
+
|
||
|
+} BC_PIB_EXT_VC1;
|
||
|
+
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * Picture Information Block *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+#if defined(_WIN32) || defined(_WIN64) || defined(__LINUX_USER__)
|
||
|
+/* Values for 'pulldown' field. '0' means no pulldown information
|
||
|
+ * was present for this picture. */
|
||
|
+enum {
|
||
|
+ vdecNoPulldownInfo = 0,
|
||
|
+ vdecTop = 1,
|
||
|
+ vdecBottom = 2,
|
||
|
+ vdecTopBottom = 3,
|
||
|
+ vdecBottomTop = 4,
|
||
|
+ vdecTopBottomTop = 5,
|
||
|
+ vdecBottomTopBottom = 6,
|
||
|
+ vdecFrame_X2 = 7,
|
||
|
+ vdecFrame_X3 = 8,
|
||
|
+ vdecFrame_X1 = 9,
|
||
|
+ vdecFrame_X4 = 10,
|
||
|
+};
|
||
|
+
|
||
|
+/* Values for the 'frame_rate' field. */
|
||
|
+enum {
|
||
|
+ vdecFrameRateUnknown = 0,
|
||
|
+ vdecFrameRate23_97,
|
||
|
+ vdecFrameRate24,
|
||
|
+ vdecFrameRate25,
|
||
|
+ vdecFrameRate29_97,
|
||
|
+ vdecFrameRate30,
|
||
|
+ vdecFrameRate50,
|
||
|
+ vdecFrameRate59_94,
|
||
|
+ vdecFrameRate60,
|
||
|
+};
|
||
|
+
|
||
|
+/* Values for the 'aspect_ratio' field. */
|
||
|
+enum {
|
||
|
+ vdecAspectRatioUnknown = 0,
|
||
|
+ vdecAspectRatioSquare,
|
||
|
+ vdecAspectRatio12_11,
|
||
|
+ vdecAspectRatio10_11,
|
||
|
+ vdecAspectRatio16_11,
|
||
|
+ vdecAspectRatio40_33,
|
||
|
+ vdecAspectRatio24_11,
|
||
|
+ vdecAspectRatio20_11,
|
||
|
+ vdecAspectRatio32_11,
|
||
|
+ vdecAspectRatio80_33,
|
||
|
+ vdecAspectRatio18_11,
|
||
|
+ vdecAspectRatio15_11,
|
||
|
+ vdecAspectRatio64_33,
|
||
|
+ vdecAspectRatio160_99,
|
||
|
+ vdecAspectRatio4_3,
|
||
|
+ vdecAspectRatio16_9,
|
||
|
+ vdecAspectRatio221_1,
|
||
|
+ vdecAspectRatioOther = 255,
|
||
|
+};
|
||
|
+
|
||
|
+/* Values for the 'colour_primaries' field. */
|
||
|
+enum {
|
||
|
+ vdecColourPrimariesUnknown = 0,
|
||
|
+ vdecColourPrimariesBT709,
|
||
|
+ vdecColourPrimariesUnspecified,
|
||
|
+ vdecColourPrimariesReserved,
|
||
|
+ vdecColourPrimariesBT470_2M = 4,
|
||
|
+ vdecColourPrimariesBT470_2BG,
|
||
|
+ vdecColourPrimariesSMPTE170M,
|
||
|
+ vdecColourPrimariesSMPTE240M,
|
||
|
+ vdecColourPrimariesGenericFilm,
|
||
|
+};
|
||
|
+
|
||
|
+enum {
|
||
|
+ vdecRESOLUTION_CUSTOM = 0x00000000, /* custom */
|
||
|
+ vdecRESOLUTION_480i = 0x00000001, /* 480i */
|
||
|
+ vdecRESOLUTION_1080i = 0x00000002, /* 1080i (1920x1080, 60i) */
|
||
|
+ vdecRESOLUTION_NTSC = 0x00000003, /* NTSC (720x483, 60i) */
|
||
|
+ vdecRESOLUTION_480p = 0x00000004, /* 480p (720x480, 60p) */
|
||
|
+ vdecRESOLUTION_720p = 0x00000005, /* 720p (1280x720, 60p) */
|
||
|
+ vdecRESOLUTION_PAL1 = 0x00000006, /* PAL_1 (720x576, 50i) */
|
||
|
+ vdecRESOLUTION_1080i25 = 0x00000007, /* 1080i25 (1920x1080, 50i) */
|
||
|
+ vdecRESOLUTION_720p50 = 0x00000008, /* 720p50 (1280x720, 50p) */
|
||
|
+ vdecRESOLUTION_576p = 0x00000009, /* 576p (720x576, 50p) */
|
||
|
+ vdecRESOLUTION_1080i29_97 = 0x0000000A, /* 1080i (1920x1080, 59.94i) */
|
||
|
+ vdecRESOLUTION_720p59_94 = 0x0000000B, /* 720p (1280x720, 59.94p) */
|
||
|
+ vdecRESOLUTION_SD_DVD = 0x0000000C, /* SD DVD (720x483, 60i) */
|
||
|
+ vdecRESOLUTION_480p656 = 0x0000000D, /* 480p (720x480, 60p), output bus width 8 bit, clock 74.25MHz */
|
||
|
+ vdecRESOLUTION_1080p23_976 = 0x0000000E, /* 1080p23_976 (1920x1080, 23.976p) */
|
||
|
+ vdecRESOLUTION_720p23_976 = 0x0000000F, /* 720p23_976 (1280x720p, 23.976p) */
|
||
|
+ vdecRESOLUTION_240p29_97 = 0x00000010, /* 240p (1440x240, 29.97p ) */
|
||
|
+ vdecRESOLUTION_240p30 = 0x00000011, /* 240p (1440x240, 30p) */
|
||
|
+ vdecRESOLUTION_288p25 = 0x00000012, /* 288p (1440x288p, 25p) */
|
||
|
+ vdecRESOLUTION_1080p29_97 = 0x00000013, /* 1080p29_97 (1920x1080, 29.97p) */
|
||
|
+ vdecRESOLUTION_1080p30 = 0x00000014, /* 1080p30 (1920x1080, 30p) */
|
||
|
+ vdecRESOLUTION_1080p24 = 0x00000015, /* 1080p24 (1920x1080, 24p) */
|
||
|
+ vdecRESOLUTION_1080p25 = 0x00000016, /* 1080p25 (1920x1080, 25p) */
|
||
|
+ vdecRESOLUTION_720p24 = 0x00000017, /* 720p24 (1280x720, 25p) */
|
||
|
+ vdecRESOLUTION_720p29_97 = 0x00000018, /* 720p29.97 (1280x720, 29.97p) */
|
||
|
+ vdecRESOLUTION_480p23_976 = 0x00000019, /* 480p23.976 (720*480, 23.976) */
|
||
|
+ vdecRESOLUTION_480p29_97 = 0x0000001A, /* 480p29.976 (720*480, 29.97p) */
|
||
|
+ vdecRESOLUTION_576p25 = 0x0000001B, /* 576p25 (720*576, 25p) */
|
||
|
+ /* For Zero Frame Rate */
|
||
|
+ vdecRESOLUTION_480p0 = 0x0000001C, /* 480p (720x480, 0p) */
|
||
|
+ vdecRESOLUTION_480i0 = 0x0000001D, /* 480i (720x480, 0i) */
|
||
|
+ vdecRESOLUTION_576p0 = 0x0000001E, /* 576p (720x576, 0p) */
|
||
|
+ vdecRESOLUTION_720p0 = 0x0000001F, /* 720p (1280x720, 0p) */
|
||
|
+ vdecRESOLUTION_1080p0 = 0x00000020, /* 1080p (1920x1080, 0p) */
|
||
|
+ vdecRESOLUTION_1080i0 = 0x00000021, /* 1080i (1920x1080, 0i) */
|
||
|
+};
|
||
|
+
|
||
|
+/* Bit definitions for 'flags' field */
|
||
|
+#define VDEC_FLAG_EOS (0x0004)
|
||
|
+
|
||
|
+#define VDEC_FLAG_FRAME (0x0000)
|
||
|
+#define VDEC_FLAG_FIELDPAIR (0x0008)
|
||
|
+#define VDEC_FLAG_TOPFIELD (0x0010)
|
||
|
+#define VDEC_FLAG_BOTTOMFIELD (0x0018)
|
||
|
+
|
||
|
+#define VDEC_FLAG_PROGRESSIVE_SRC (0x0000)
|
||
|
+#define VDEC_FLAG_INTERLACED_SRC (0x0020)
|
||
|
+#define VDEC_FLAG_UNKNOWN_SRC (0x0040)
|
||
|
+
|
||
|
+#define VDEC_FLAG_BOTTOM_FIRST (0x0080)
|
||
|
+#define VDEC_FLAG_LAST_PICTURE (0x0100)
|
||
|
+
|
||
|
+#define VDEC_FLAG_PICTURE_META_DATA_PRESENT (0x40000)
|
||
|
+
|
||
|
+#endif /* _WIN32 || _WIN64 */
|
||
|
+
|
||
|
+enum _BC_OUTPUT_FORMAT {
|
||
|
+ MODE420 = 0x0,
|
||
|
+ MODE422_YUY2 = 0x1,
|
||
|
+ MODE422_UYVY = 0x2,
|
||
|
+};
|
||
|
+
|
||
|
+typedef struct _BC_PIC_INFO_BLOCK {
|
||
|
+ /* Common fields. */
|
||
|
+ uint64_t timeStamp; /* Timestamp */
|
||
|
+ uint32_t picture_number; /* Ordinal display number */
|
||
|
+ uint32_t width; /* pixels */
|
||
|
+ uint32_t height; /* pixels */
|
||
|
+ uint32_t chroma_format; /* 0x420, 0x422 or 0x444 */
|
||
|
+ uint32_t pulldown;
|
||
|
+ uint32_t flags;
|
||
|
+ uint32_t frame_rate;
|
||
|
+ uint32_t aspect_ratio;
|
||
|
+ uint32_t colour_primaries;
|
||
|
+ uint32_t picture_meta_payload;
|
||
|
+ uint32_t sess_num;
|
||
|
+ uint32_t ycom;
|
||
|
+ uint32_t custom_aspect_ratio_width_height;
|
||
|
+ uint32_t n_drop; /* number of non-reference frames remaining to be dropped */
|
||
|
+
|
||
|
+ /* Protocol-specific extensions. */
|
||
|
+ union {
|
||
|
+ BC_PIB_EXT_H264 h264;
|
||
|
+ BC_PIB_EXT_MPEG mpeg;
|
||
|
+ BC_PIB_EXT_VC1 vc1;
|
||
|
+ } other;
|
||
|
+
|
||
|
+} BC_PIC_INFO_BLOCK, *PBC_PIC_INFO_BLOCK;
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * ProcOut Info *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+/* Optional flags for ProcOut Interface.*/
|
||
|
+enum _POUT_OPTIONAL_IN_FLAGS_{
|
||
|
+ /* Flags from App to Device */
|
||
|
+ BC_POUT_FLAGS_YV12 = 0x01, /* Copy Data in YV12 format */
|
||
|
+ BC_POUT_FLAGS_STRIDE = 0x02, /* Stride size is valid. */
|
||
|
+ BC_POUT_FLAGS_SIZE = 0x04, /* Take size information from Application */
|
||
|
+ BC_POUT_FLAGS_INTERLACED = 0x08, /* copy only half the bytes */
|
||
|
+ BC_POUT_FLAGS_INTERLEAVED = 0x10, /* interleaved frame */
|
||
|
+
|
||
|
+ /* Flags from Device to APP */
|
||
|
+ BC_POUT_FLAGS_FMT_CHANGE = 0x10000, /* Data is not VALID when this flag is set */
|
||
|
+ BC_POUT_FLAGS_PIB_VALID = 0x20000, /* PIB Information valid */
|
||
|
+ BC_POUT_FLAGS_ENCRYPTED = 0x40000, /* Data is encrypted. */
|
||
|
+ BC_POUT_FLAGS_FLD_BOT = 0x80000, /* Bottom Field data */
|
||
|
+};
|
||
|
+
|
||
|
+#if defined(__KERNEL__) || defined(__LINUX_USER__)
|
||
|
+typedef BC_STATUS(*dts_pout_callback)(void *shnd, uint32_t width, uint32_t height, uint32_t stride, void *pOut);
|
||
|
+#else
|
||
|
+typedef BC_STATUS(*dts_pout_callback)(void *shnd, uint32_t width, uint32_t height, uint32_t stride, struct _BC_DTS_PROC_OUT *pOut);
|
||
|
+#endif
|
||
|
+
|
||
|
+/* Line 21 Closed Caption */
|
||
|
+/* User Data */
|
||
|
+#define MAX_UD_SIZE 1792 /* 1920 - 128 */
|
||
|
+
|
||
|
+typedef struct _BC_DTS_PROC_OUT {
|
||
|
+ uint8_t *Ybuff; /* Caller Supplied buffer for Y data */
|
||
|
+ uint32_t YbuffSz; /* Caller Supplied Y buffer size */
|
||
|
+ uint32_t YBuffDoneSz; /* Transferred Y datasize */
|
||
|
+
|
||
|
+ uint8_t *UVbuff; /* Caller Supplied buffer for UV data */
|
||
|
+ uint32_t UVbuffSz; /* Caller Supplied UV buffer size */
|
||
|
+ uint32_t UVBuffDoneSz; /* Transferred UV data size */
|
||
|
+
|
||
|
+ uint32_t StrideSz; /* Caller supplied Stride Size */
|
||
|
+ uint32_t PoutFlags; /* Call IN Flags */
|
||
|
+
|
||
|
+ uint32_t discCnt; /* Picture discontinuity count */
|
||
|
+
|
||
|
+ BC_PIC_INFO_BLOCK PicInfo; /* Picture Information Block Data */
|
||
|
+
|
||
|
+ /* Line 21 Closed Caption */
|
||
|
+ /* User Data */
|
||
|
+ uint32_t UserDataSz;
|
||
|
+ uint8_t UserData[MAX_UD_SIZE];
|
||
|
+
|
||
|
+ void *hnd;
|
||
|
+ dts_pout_callback AppCallBack;
|
||
|
+ uint8_t DropFrames;
|
||
|
+ uint8_t b422Mode; /* Picture output Mode */
|
||
|
+ uint8_t bPibEnc; /* PIB encrypted */
|
||
|
+ uint8_t bRevertScramble;
|
||
|
+
|
||
|
+} BC_DTS_PROC_OUT;
|
||
|
+
|
||
|
+typedef struct _BC_DTS_STATUS {
|
||
|
+ uint8_t ReadyListCount; /* Number of frames in ready list (reported by driver) */
|
||
|
+ uint8_t FreeListCount; /* Number of frame buffers free. (reported by driver) */
|
||
|
+ uint8_t PowerStateChange; /* Number of active state power transitions (reported by driver) */
|
||
|
+ uint8_t reserved_[1];
|
||
|
+
|
||
|
+ uint32_t FramesDropped; /* Number of frames dropped. (reported by DIL) */
|
||
|
+ uint32_t FramesCaptured; /* Number of frames captured. (reported by DIL) */
|
||
|
+ uint32_t FramesRepeated; /* Number of frames repeated. (reported by DIL) */
|
||
|
+
|
||
|
+ uint32_t InputCount; /* Times compressed video has been sent to the HW.
|
||
|
+ * i.e. Successful DtsProcInput() calls (reported by DIL) */
|
||
|
+ uint64_t InputTotalSize; /* Amount of compressed video that has been sent to the HW.
|
||
|
+ * (reported by DIL) */
|
||
|
+ uint32_t InputBusyCount; /* Times compressed video has attempted to be sent to the HW
|
||
|
+ * but the input FIFO was full. (reported by DIL) */
|
||
|
+
|
||
|
+ uint32_t PIBMissCount; /* Amount of times a PIB is invalid. (reported by DIL) */
|
||
|
+
|
||
|
+ uint32_t cpbEmptySize; /* supported only for H.264, specifically changed for
|
||
|
+ * Adobe. Report size of CPB buffer available.
|
||
|
+ * Reported by DIL */
|
||
|
+ uint64_t NextTimeStamp; /* TimeStamp of the next picture that will be returned
|
||
|
+ * by a call to ProcOutput. Added for Adobe. Reported
|
||
|
+ * back from the driver */
|
||
|
+ uint8_t reserved__[16];
|
||
|
+
|
||
|
+} BC_DTS_STATUS;
|
||
|
+
|
||
|
+#define BC_SWAP32(_v) \
|
||
|
+ ((((_v) & 0xFF000000)>>24)| \
|
||
|
+ (((_v) & 0x00FF0000)>>8)| \
|
||
|
+ (((_v) & 0x0000FF00)<<8)| \
|
||
|
+ (((_v) & 0x000000FF)<<24))
|
||
|
+
|
||
|
+#define WM_AGENT_TRAYICON_DECODER_OPEN 10001
|
||
|
+#define WM_AGENT_TRAYICON_DECODER_CLOSE 10002
|
||
|
+#define WM_AGENT_TRAYICON_DECODER_START 10003
|
||
|
+#define WM_AGENT_TRAYICON_DECODER_STOP 10004
|
||
|
+#define WM_AGENT_TRAYICON_DECODER_RUN 10005
|
||
|
+#define WM_AGENT_TRAYICON_DECODER_PAUSE 10006
|
||
|
+
|
||
|
+
|
||
|
+#endif /* _BC_DTS_DEFS_H_ */
|
||
|
diff --git a/drivers/staging/crystalhd/bc_dts_glob_lnx.h b/drivers/staging/crystalhd/bc_dts_glob_lnx.h
|
||
|
new file mode 100644
|
||
|
index 0000000..b3125e3
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/bc_dts_glob_lnx.h
|
||
|
@@ -0,0 +1,299 @@
|
||
|
+/********************************************************************
|
||
|
+ * Copyright(c) 2006-2009 Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: bc_dts_glob_lnx.h
|
||
|
+ *
|
||
|
+ * Description: Wrapper to Windows dts_glob.h for Link-Linux usage.
|
||
|
+ * The idea is to define additional Linux related defs
|
||
|
+ * in this file to avoid changes to existing Windows
|
||
|
+ * glob file.
|
||
|
+ *
|
||
|
+ * AU
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ ********************************************************************
|
||
|
+ * This header is free software: you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU Lesser General Public License as published
|
||
|
+ * by the Free Software Foundation, either version 2.1 of the License.
|
||
|
+ *
|
||
|
+ * This header is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU Lesser General Public License for more details.
|
||
|
+ * You should have received a copy of the GNU Lesser General Public License
|
||
|
+ * along with this header. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ *******************************************************************/
|
||
|
+
|
||
|
+#ifndef _BC_DTS_GLOB_LNX_H_
|
||
|
+#define _BC_DTS_GLOB_LNX_H_
|
||
|
+
|
||
|
+#ifdef __LINUX_USER__
|
||
|
+#include <stdio.h>
|
||
|
+#include <stdlib.h>
|
||
|
+#include <unistd.h>
|
||
|
+#include <fcntl.h>
|
||
|
+#include <ctype.h>
|
||
|
+#include <string.h>
|
||
|
+#include <errno.h>
|
||
|
+#include <netdb.h>
|
||
|
+#include <sys/time.h>
|
||
|
+#include <time.h>
|
||
|
+#include <arpa/inet.h>
|
||
|
+#include <asm/param.h>
|
||
|
+#include <linux/ioctl.h>
|
||
|
+#include <sys/select.h>
|
||
|
+
|
||
|
+#define DRVIFLIB_INT_API
|
||
|
+
|
||
|
+#endif
|
||
|
+
|
||
|
+#include "bc_dts_defs.h"
|
||
|
+#include "bcm_70012_regs.h" /* Link Register defs */
|
||
|
+
|
||
|
+#define CRYSTALHD_API_NAME "crystalhd"
|
||
|
+#define CRYSTALHD_API_DEV_NAME "/dev/crystalhd"
|
||
|
+
|
||
|
+/*
|
||
|
+ * These are SW stack tunable parameters shared
|
||
|
+ * between the driver and the application.
|
||
|
+ */
|
||
|
+enum _BC_DTS_GLOBALS {
|
||
|
+ BC_MAX_FW_CMD_BUFF_SZ = 0x40, /* FW passthrough cmd/rsp buffer size */
|
||
|
+ PCI_CFG_SIZE = 256, /* PCI config size buffer */
|
||
|
+ BC_IOCTL_DATA_POOL_SIZE = 8, /* BC_IOCTL_DATA Pool size */
|
||
|
+ BC_LINK_MAX_OPENS = 3, /* Maximum simultaneous opens*/
|
||
|
+ BC_LINK_MAX_SGLS = 1024, /* Maximum SG elements 4M/4K */
|
||
|
+ BC_TX_LIST_CNT = 2, /* Max Tx DMA Rings */
|
||
|
+ BC_RX_LIST_CNT = 8, /* Max Rx DMA Rings*/
|
||
|
+ BC_PROC_OUTPUT_TIMEOUT = 3000, /* Milliseconds */
|
||
|
+ BC_INFIFO_THRESHOLD = 0x10000,
|
||
|
+};
|
||
|
+
|
||
|
+typedef struct _BC_CMD_REG_ACC {
|
||
|
+ uint32_t Offset;
|
||
|
+ uint32_t Value;
|
||
|
+} BC_CMD_REG_ACC;
|
||
|
+
|
||
|
+typedef struct _BC_CMD_DEV_MEM {
|
||
|
+ uint32_t StartOff;
|
||
|
+ uint32_t NumDwords;
|
||
|
+ uint32_t Rsrd;
|
||
|
+} BC_CMD_DEV_MEM;
|
||
|
+
|
||
|
+/* FW Passthrough command structure */
|
||
|
+enum _bc_fw_cmd_flags {
|
||
|
+ BC_FW_CMD_FLAGS_NONE = 0,
|
||
|
+ BC_FW_CMD_PIB_QS = 0x01,
|
||
|
+};
|
||
|
+
|
||
|
+typedef struct _BC_FW_CMD {
|
||
|
+ uint32_t cmd[BC_MAX_FW_CMD_BUFF_SZ];
|
||
|
+ uint32_t rsp[BC_MAX_FW_CMD_BUFF_SZ];
|
||
|
+ uint32_t flags;
|
||
|
+ uint32_t add_data;
|
||
|
+} BC_FW_CMD, *PBC_FW_CMD;
|
||
|
+
|
||
|
+typedef struct _BC_HW_TYPE {
|
||
|
+ uint16_t PciDevId;
|
||
|
+ uint16_t PciVenId;
|
||
|
+ uint8_t HwRev;
|
||
|
+ uint8_t Align[3];
|
||
|
+} BC_HW_TYPE;
|
||
|
+
|
||
|
+typedef struct _BC_PCI_CFG {
|
||
|
+ uint32_t Size;
|
||
|
+ uint32_t Offset;
|
||
|
+ uint8_t pci_cfg_space[PCI_CFG_SIZE];
|
||
|
+} BC_PCI_CFG;
|
||
|
+
|
||
|
+typedef struct _BC_VERSION_INFO_ {
|
||
|
+ uint8_t DriverMajor;
|
||
|
+ uint8_t DriverMinor;
|
||
|
+ uint16_t DriverRevision;
|
||
|
+} BC_VERSION_INFO;
|
||
|
+
|
||
|
+typedef struct _BC_START_RX_CAP_ {
|
||
|
+ uint32_t Rsrd;
|
||
|
+ uint32_t StartDeliveryThsh;
|
||
|
+ uint32_t PauseThsh;
|
||
|
+ uint32_t ResumeThsh;
|
||
|
+} BC_START_RX_CAP;
|
||
|
+
|
||
|
+typedef struct _BC_FLUSH_RX_CAP_ {
|
||
|
+ uint32_t Rsrd;
|
||
|
+ uint32_t bDiscardOnly;
|
||
|
+} BC_FLUSH_RX_CAP;
|
||
|
+
|
||
|
+typedef struct _BC_DTS_STATS {
|
||
|
+ uint8_t drvRLL;
|
||
|
+ uint8_t drvFLL;
|
||
|
+ uint8_t eosDetected;
|
||
|
+ uint8_t pwr_state_change;
|
||
|
+
|
||
|
+ /* Stats from App */
|
||
|
+ uint32_t opFrameDropped;
|
||
|
+ uint32_t opFrameCaptured;
|
||
|
+ uint32_t ipSampleCnt;
|
||
|
+ uint64_t ipTotalSize;
|
||
|
+ uint32_t reptdFrames;
|
||
|
+ uint32_t pauseCount;
|
||
|
+ uint32_t pibMisses;
|
||
|
+ uint32_t discCounter;
|
||
|
+
|
||
|
+ /* Stats from Driver */
|
||
|
+ uint32_t TxFifoBsyCnt;
|
||
|
+ uint32_t intCount;
|
||
|
+ uint32_t DrvIgnIntrCnt;
|
||
|
+ uint32_t DrvTotalFrmDropped;
|
||
|
+ uint32_t DrvTotalHWErrs;
|
||
|
+ uint32_t DrvTotalPIBFlushCnt;
|
||
|
+ uint32_t DrvTotalFrmCaptured;
|
||
|
+ uint32_t DrvPIBMisses;
|
||
|
+ uint32_t DrvPauseTime;
|
||
|
+ uint32_t DrvRepeatedFrms;
|
||
|
+ uint32_t res1[13];
|
||
|
+
|
||
|
+} BC_DTS_STATS;
|
||
|
+
|
||
|
+typedef struct _BC_PROC_INPUT_ {
|
||
|
+ uint8_t *pDmaBuff;
|
||
|
+ uint32_t BuffSz;
|
||
|
+ uint8_t Mapped;
|
||
|
+ uint8_t Encrypted;
|
||
|
+ uint8_t Rsrd[2];
|
||
|
+ uint32_t DramOffset; /* For debug use only */
|
||
|
+} BC_PROC_INPUT, *PBC_PROC_INPUT;
|
||
|
+
|
||
|
+typedef struct _BC_DEC_YUV_BUFFS {
|
||
|
+ uint32_t b422Mode;
|
||
|
+ uint8_t *YuvBuff;
|
||
|
+ uint32_t YuvBuffSz;
|
||
|
+ uint32_t UVbuffOffset;
|
||
|
+ uint32_t YBuffDoneSz;
|
||
|
+ uint32_t UVBuffDoneSz;
|
||
|
+ uint32_t RefCnt;
|
||
|
+} BC_DEC_YUV_BUFFS;
|
||
|
+
|
||
|
+enum _DECOUT_COMPLETION_FLAGS{
|
||
|
+ COMP_FLAG_NO_INFO = 0x00,
|
||
|
+ COMP_FLAG_FMT_CHANGE = 0x01,
|
||
|
+ COMP_FLAG_PIB_VALID = 0x02,
|
||
|
+ COMP_FLAG_DATA_VALID = 0x04,
|
||
|
+ COMP_FLAG_DATA_ENC = 0x08,
|
||
|
+ COMP_FLAG_DATA_BOT = 0x10,
|
||
|
+};
|
||
|
+
|
||
|
+typedef struct _BC_DEC_OUT_BUFF{
|
||
|
+ BC_DEC_YUV_BUFFS OutPutBuffs;
|
||
|
+ BC_PIC_INFO_BLOCK PibInfo;
|
||
|
+ uint32_t Flags;
|
||
|
+ uint32_t BadFrCnt;
|
||
|
+} BC_DEC_OUT_BUFF;
|
||
|
+
|
||
|
+typedef struct _BC_NOTIFY_MODE {
|
||
|
+ uint32_t Mode;
|
||
|
+ uint32_t Rsvr[3];
|
||
|
+} BC_NOTIFY_MODE;
|
||
|
+
|
||
|
+typedef struct _BC_CLOCK {
|
||
|
+ uint32_t clk;
|
||
|
+ uint32_t Rsvr[3];
|
||
|
+} BC_CLOCK;
|
||
|
+
|
||
|
+typedef struct _BC_IOCTL_DATA {
|
||
|
+ BC_STATUS RetSts;
|
||
|
+ uint32_t IoctlDataSz;
|
||
|
+ uint32_t Timeout;
|
||
|
+ union {
|
||
|
+ BC_CMD_REG_ACC regAcc;
|
||
|
+ BC_CMD_DEV_MEM devMem;
|
||
|
+ BC_FW_CMD fwCmd;
|
||
|
+ BC_HW_TYPE hwType;
|
||
|
+ BC_PCI_CFG pciCfg;
|
||
|
+ BC_VERSION_INFO VerInfo;
|
||
|
+ BC_PROC_INPUT ProcInput;
|
||
|
+ BC_DEC_YUV_BUFFS RxBuffs;
|
||
|
+ BC_DEC_OUT_BUFF DecOutData;
|
||
|
+ BC_START_RX_CAP RxCap;
|
||
|
+ BC_FLUSH_RX_CAP FlushRxCap;
|
||
|
+ BC_DTS_STATS drvStat;
|
||
|
+ BC_NOTIFY_MODE NotifyMode;
|
||
|
+ BC_CLOCK clockValue;
|
||
|
+ } u;
|
||
|
+ struct _BC_IOCTL_DATA *next;
|
||
|
+} BC_IOCTL_DATA;
|
||
|
+
|
||
|
+typedef enum _BC_DRV_CMD{
|
||
|
+ DRV_CMD_VERSION = 0, /* Get SW version */
|
||
|
+ DRV_CMD_GET_HWTYPE, /* Get HW version and type Dozer/Tank */
|
||
|
+ DRV_CMD_REG_RD, /* Read Device Register */
|
||
|
+ DRV_CMD_REG_WR, /* Write Device Register */
|
||
|
+ DRV_CMD_FPGA_RD, /* Read FPGA Register */
|
||
|
+ DRV_CMD_FPGA_WR, /* Wrtie FPGA Reister */
|
||
|
+ DRV_CMD_MEM_RD, /* Read Device Memory */
|
||
|
+ DRV_CMD_MEM_WR, /* Write Device Memory */
|
||
|
+ DRV_CMD_RD_PCI_CFG, /* Read PCI Config Space */
|
||
|
+ DRV_CMD_WR_PCI_CFG, /* Write the PCI Configuration Space*/
|
||
|
+ DRV_CMD_FW_DOWNLOAD, /* Download Firmware */
|
||
|
+ DRV_ISSUE_FW_CMD, /* Issue FW Cmd (pass through mode) */
|
||
|
+ DRV_CMD_PROC_INPUT, /* Process Input Sample */
|
||
|
+ DRV_CMD_ADD_RXBUFFS, /* Add Rx side buffers to driver pool */
|
||
|
+ DRV_CMD_FETCH_RXBUFF, /* Get Rx DMAed buffer */
|
||
|
+ DRV_CMD_START_RX_CAP, /* Start Rx Buffer Capture */
|
||
|
+ DRV_CMD_FLUSH_RX_CAP, /* Stop the capture for now...we will enhance this later*/
|
||
|
+ DRV_CMD_GET_DRV_STAT, /* Get Driver Internal Statistics */
|
||
|
+ DRV_CMD_RST_DRV_STAT, /* Reset Driver Internal Statistics */
|
||
|
+ DRV_CMD_NOTIFY_MODE, /* Notify the Mode to driver in which the application is Operating*/
|
||
|
+ DRV_CMD_CHANGE_CLOCK, /* Change the core clock to either save power or improve performance */
|
||
|
+
|
||
|
+ /* MUST be the last one.. */
|
||
|
+ DRV_CMD_END, /* End of the List.. */
|
||
|
+} BC_DRV_CMD;
|
||
|
+
|
||
|
+#define BC_IOC_BASE 'b'
|
||
|
+#define BC_IOC_VOID _IOC_NONE
|
||
|
+#define BC_IOC_IOWR(nr, type) _IOWR(BC_IOC_BASE, nr, type)
|
||
|
+#define BC_IOCTL_MB BC_IOCTL_DATA
|
||
|
+
|
||
|
+#define BCM_IOC_GET_VERSION BC_IOC_IOWR(DRV_CMD_VERSION, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_GET_HWTYPE BC_IOC_IOWR(DRV_CMD_GET_HWTYPE, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_REG_RD BC_IOC_IOWR(DRV_CMD_REG_RD, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_REG_WR BC_IOC_IOWR(DRV_CMD_REG_WR, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_MEM_RD BC_IOC_IOWR(DRV_CMD_MEM_RD, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_MEM_WR BC_IOC_IOWR(DRV_CMD_MEM_WR, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_FPGA_RD BC_IOC_IOWR(DRV_CMD_FPGA_RD, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_FPGA_WR BC_IOC_IOWR(DRV_CMD_FPGA_WR, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_RD_PCI_CFG BC_IOC_IOWR(DRV_CMD_RD_PCI_CFG, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_WR_PCI_CFG BC_IOC_IOWR(DRV_CMD_WR_PCI_CFG, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_PROC_INPUT BC_IOC_IOWR(DRV_CMD_PROC_INPUT, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_ADD_RXBUFFS BC_IOC_IOWR(DRV_CMD_ADD_RXBUFFS, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_FETCH_RXBUFF BC_IOC_IOWR(DRV_CMD_FETCH_RXBUFF, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_FW_CMD BC_IOC_IOWR(DRV_ISSUE_FW_CMD, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_START_RX_CAP BC_IOC_IOWR(DRV_CMD_START_RX_CAP, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_FLUSH_RX_CAP BC_IOC_IOWR(DRV_CMD_FLUSH_RX_CAP, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_GET_DRV_STAT BC_IOC_IOWR(DRV_CMD_GET_DRV_STAT, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_RST_DRV_STAT BC_IOC_IOWR(DRV_CMD_RST_DRV_STAT, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_NOTIFY_MODE BC_IOC_IOWR(DRV_CMD_NOTIFY_MODE, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_FW_DOWNLOAD BC_IOC_IOWR(DRV_CMD_FW_DOWNLOAD, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_CHG_CLK BC_IOC_IOWR(DRV_CMD_CHANGE_CLOCK, BC_IOCTL_MB)
|
||
|
+#define BCM_IOC_END BC_IOC_VOID
|
||
|
+
|
||
|
+/* Wrapper for main IOCTL data */
|
||
|
+typedef struct _crystalhd_ioctl_data {
|
||
|
+ BC_IOCTL_DATA udata; /* IOCTL from App..*/
|
||
|
+ uint32_t u_id; /* Driver specific user ID */
|
||
|
+ uint32_t cmd; /* Cmd ID for driver's use. */
|
||
|
+ void *add_cdata; /* Additional command specific data..*/
|
||
|
+ uint32_t add_cdata_sz; /* Additional command specific data size */
|
||
|
+ struct _crystalhd_ioctl_data *next; /* List/Fifo management */
|
||
|
+} crystalhd_ioctl_data;
|
||
|
+
|
||
|
+
|
||
|
+enum _crystalhd_kmod_ver{
|
||
|
+ crystalhd_kmod_major = 0,
|
||
|
+ crystalhd_kmod_minor = 9,
|
||
|
+ crystalhd_kmod_rev = 27,
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/staging/crystalhd/bc_dts_types.h b/drivers/staging/crystalhd/bc_dts_types.h
|
||
|
new file mode 100644
|
||
|
index 0000000..ac0c817
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/bc_dts_types.h
|
||
|
@@ -0,0 +1,121 @@
|
||
|
+/********************************************************************
|
||
|
+ * Copyright(c) 2006-2009 Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: bc_dts_types.h
|
||
|
+ *
|
||
|
+ * Description: Data types
|
||
|
+ *
|
||
|
+ * AU
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ ********************************************************************
|
||
|
+ * This header is free software: you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU Lesser General Public License as published
|
||
|
+ * by the Free Software Foundation, either version 2.1 of the License.
|
||
|
+ *
|
||
|
+ * This header is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU Lesser General Public License for more details.
|
||
|
+ * You should have received a copy of the GNU Lesser General Public License
|
||
|
+ * along with this header. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ *******************************************************************/
|
||
|
+
|
||
|
+#ifndef _BC_DTS_TYPES_H_
|
||
|
+#define _BC_DTS_TYPES_H_
|
||
|
+
|
||
|
+#ifdef __LINUX_USER__ // Don't include these for KERNEL..
|
||
|
+#include <stdint.h>
|
||
|
+#endif
|
||
|
+
|
||
|
+#if defined(_WIN64) || defined(_WIN32)
|
||
|
+typedef uint32_t U32;
|
||
|
+typedef int32_t S32;
|
||
|
+typedef uint16_t U16;
|
||
|
+typedef int16_t S16;
|
||
|
+typedef unsigned char U8;
|
||
|
+typedef char S8;
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifndef PVOID
|
||
|
+typedef void *PVOID;
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifndef BOOL
|
||
|
+typedef int BOOL;
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifdef WIN32
|
||
|
+ typedef unsigned __int64 U64;
|
||
|
+#elif defined(_WIN64)
|
||
|
+ typedef uint64_t U64;
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifdef _WIN64
|
||
|
+#if !(defined(POINTER_32))
|
||
|
+#define POINTER_32 __ptr32
|
||
|
+#endif
|
||
|
+#else /* _WIN32 */
|
||
|
+#define POINTER_32
|
||
|
+#endif
|
||
|
+
|
||
|
+#if defined(__KERNEL__) || defined(__LINUX_USER__)
|
||
|
+
|
||
|
+#ifdef __LINUX_USER__ /* Don't include these for KERNEL */
|
||
|
+typedef uint32_t ULONG;
|
||
|
+typedef int32_t LONG;
|
||
|
+typedef void *HANDLE;
|
||
|
+#ifndef VOID
|
||
|
+typedef void VOID;
|
||
|
+#endif
|
||
|
+typedef void *LPVOID;
|
||
|
+typedef uint32_t DWORD;
|
||
|
+typedef uint32_t UINT32;
|
||
|
+typedef uint32_t *LPDWORD;
|
||
|
+typedef unsigned char *PUCHAR;
|
||
|
+
|
||
|
+#ifndef TRUE
|
||
|
+ #define TRUE 1
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifndef FALSE
|
||
|
+ #define FALSE 0
|
||
|
+#endif
|
||
|
+
|
||
|
+#define TEXT
|
||
|
+
|
||
|
+#else
|
||
|
+
|
||
|
+/* For Kernel usage.. */
|
||
|
+typedef bool bc_bool_t;
|
||
|
+#endif
|
||
|
+
|
||
|
+#else
|
||
|
+
|
||
|
+#ifndef uint64_t
|
||
|
+typedef struct _uint64_t {
|
||
|
+ uint32_t low_dw;
|
||
|
+ uint32_t hi_dw;
|
||
|
+} uint64_t;
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifndef int32_t
|
||
|
+typedef signed long int32_t;
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifndef uint32_t
|
||
|
+typedef unsigned long uint32_t;
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifndef uint16_t
|
||
|
+typedef unsigned short uint16_t;
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifndef uint8_t
|
||
|
+typedef unsigned char uint8_t;
|
||
|
+#endif
|
||
|
+#endif
|
||
|
+
|
||
|
+#endif
|
||
|
+
|
||
|
diff --git a/drivers/staging/crystalhd/bcm_70012_regs.h b/drivers/staging/crystalhd/bcm_70012_regs.h
|
||
|
new file mode 100644
|
||
|
index 0000000..6922f54
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/bcm_70012_regs.h
|
||
|
@@ -0,0 +1,757 @@
|
||
|
+/***************************************************************************
|
||
|
+ * Copyright (c) 1999-2009, Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: bcm_70012_regs.h
|
||
|
+ *
|
||
|
+ * Description: BCM70012 registers
|
||
|
+ *
|
||
|
+ ********************************************************************
|
||
|
+ * This header is free software: you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU Lesser General Public License as published
|
||
|
+ * by the Free Software Foundation, either version 2.1 of the License.
|
||
|
+ *
|
||
|
+ * This header is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU Lesser General Public License for more details.
|
||
|
+ * You should have received a copy of the GNU Lesser General Public License
|
||
|
+ * along with this header. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ ***************************************************************************/
|
||
|
+
|
||
|
+#ifndef MACFILE_H__
|
||
|
+#define MACFILE_H__
|
||
|
+
|
||
|
+/**
|
||
|
+ * m = memory, c = core, r = register, f = field, d = data.
|
||
|
+ */
|
||
|
+#if !defined(GET_FIELD) && !defined(SET_FIELD)
|
||
|
+#define BRCM_ALIGN(c,r,f) c##_##r##_##f##_ALIGN
|
||
|
+#define BRCM_BITS(c,r,f) c##_##r##_##f##_BITS
|
||
|
+#define BRCM_MASK(c,r,f) c##_##r##_##f##_MASK
|
||
|
+#define BRCM_SHIFT(c,r,f) c##_##r##_##f##_SHIFT
|
||
|
+
|
||
|
+#define GET_FIELD(m,c,r,f) \
|
||
|
+ ((((m) & BRCM_MASK(c,r,f)) >> BRCM_SHIFT(c,r,f)) << BRCM_ALIGN(c,r,f))
|
||
|
+
|
||
|
+#define SET_FIELD(m,c,r,f,d) \
|
||
|
+ ((m) = (((m) & ~BRCM_MASK(c,r,f)) | ((((d) >> BRCM_ALIGN(c,r,f)) << \
|
||
|
+ BRCM_SHIFT(c,r,f)) & BRCM_MASK(c,r,f))) \
|
||
|
+ )
|
||
|
+
|
||
|
+#define SET_TYPE_FIELD(m,c,r,f,d) SET_FIELD(m,c,r,f,c##_##d)
|
||
|
+#define SET_NAME_FIELD(m,c,r,f,d) SET_FIELD(m,c,r,f,c##_##r##_##f##_##d)
|
||
|
+#define SET_VALUE_FIELD(m,c,r,f,d) SET_FIELD(m,c,r,f,d)
|
||
|
+
|
||
|
+#endif /* GET & SET */
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Core Enums.
|
||
|
+ ***************************************************************************/
|
||
|
+/****************************************************************************
|
||
|
+ * Enums: AES_RGR_BRIDGE_RESET_CTRL
|
||
|
+ ***************************************************************************/
|
||
|
+#define AES_RGR_BRIDGE_RESET_CTRL_DEASSERT 0
|
||
|
+#define AES_RGR_BRIDGE_RESET_CTRL_ASSERT 1
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Enums: CCE_RGR_BRIDGE_RESET_CTRL
|
||
|
+ ***************************************************************************/
|
||
|
+#define CCE_RGR_BRIDGE_RESET_CTRL_DEASSERT 0
|
||
|
+#define CCE_RGR_BRIDGE_RESET_CTRL_ASSERT 1
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Enums: DBU_RGR_BRIDGE_RESET_CTRL
|
||
|
+ ***************************************************************************/
|
||
|
+#define DBU_RGR_BRIDGE_RESET_CTRL_DEASSERT 0
|
||
|
+#define DBU_RGR_BRIDGE_RESET_CTRL_ASSERT 1
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Enums: DCI_RGR_BRIDGE_RESET_CTRL
|
||
|
+ ***************************************************************************/
|
||
|
+#define DCI_RGR_BRIDGE_RESET_CTRL_DEASSERT 0
|
||
|
+#define DCI_RGR_BRIDGE_RESET_CTRL_ASSERT 1
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Enums: GISB_ARBITER_DEASSERT_ASSERT
|
||
|
+ ***************************************************************************/
|
||
|
+#define GISB_ARBITER_DEASSERT_ASSERT_DEASSERT 0
|
||
|
+#define GISB_ARBITER_DEASSERT_ASSERT_ASSERT 1
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Enums: GISB_ARBITER_UNMASK_MASK
|
||
|
+ ***************************************************************************/
|
||
|
+#define GISB_ARBITER_UNMASK_MASK_UNMASK 0
|
||
|
+#define GISB_ARBITER_UNMASK_MASK_MASK 1
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Enums: GISB_ARBITER_DISABLE_ENABLE
|
||
|
+ ***************************************************************************/
|
||
|
+#define GISB_ARBITER_DISABLE_ENABLE_DISABLE 0
|
||
|
+#define GISB_ARBITER_DISABLE_ENABLE_ENABLE 1
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Enums: I2C_GR_BRIDGE_RESET_CTRL
|
||
|
+ ***************************************************************************/
|
||
|
+#define I2C_GR_BRIDGE_RESET_CTRL_DEASSERT 0
|
||
|
+#define I2C_GR_BRIDGE_RESET_CTRL_ASSERT 1
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Enums: MISC_GR_BRIDGE_RESET_CTRL
|
||
|
+ ***************************************************************************/
|
||
|
+#define MISC_GR_BRIDGE_RESET_CTRL_DEASSERT 0
|
||
|
+#define MISC_GR_BRIDGE_RESET_CTRL_ASSERT 1
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Enums: OTP_GR_BRIDGE_RESET_CTRL
|
||
|
+ ***************************************************************************/
|
||
|
+#define OTP_GR_BRIDGE_RESET_CTRL_DEASSERT 0
|
||
|
+#define OTP_GR_BRIDGE_RESET_CTRL_ASSERT 1
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_TGT_TOP_PCIE_CFG
|
||
|
+ ***************************************************************************/
|
||
|
+#define PCIE_CFG_DEVICE_VENDOR_ID 0x00000000 /* DEVICE_VENDOR_ID Register */
|
||
|
+#define PCIE_CFG_STATUS_COMMAND 0x00000004 /* STATUS_COMMAND Register */
|
||
|
+#define PCIE_CFG_PCI_CLASSCODE_AND_REVISION_ID 0x00000008 /* PCI_CLASSCODE_AND_REVISION_ID Register */
|
||
|
+#define PCIE_CFG_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE_SIZE 0x0000000c /* BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE_SIZE Register */
|
||
|
+#define PCIE_CFG_BASE_ADDRESS_1 0x00000010 /* BASE_ADDRESS_1 Register */
|
||
|
+#define PCIE_CFG_BASE_ADDRESS_2 0x00000014 /* BASE_ADDRESS_2 Register */
|
||
|
+#define PCIE_CFG_BASE_ADDRESS_3 0x00000018 /* BASE_ADDRESS_3 Register */
|
||
|
+#define PCIE_CFG_BASE_ADDRESS_4 0x0000001c /* BASE_ADDRESS_4 Register */
|
||
|
+#define PCIE_CFG_CARDBUS_CIS_POINTER 0x00000028 /* CARDBUS_CIS_POINTER Register */
|
||
|
+#define PCIE_CFG_SUBSYSTEM_DEVICE_VENDOR_ID 0x0000002c /* SUBSYSTEM_DEVICE_VENDOR_ID Register */
|
||
|
+#define PCIE_CFG_EXPANSION_ROM_BASE_ADDRESS 0x00000030 /* EXPANSION_ROM_BASE_ADDRESS Register */
|
||
|
+#define PCIE_CFG_CAPABILITIES_POINTER 0x00000034 /* CAPABILITIES_POINTER Register */
|
||
|
+#define PCIE_CFG_INTERRUPT 0x0000003c /* INTERRUPT Register */
|
||
|
+#define PCIE_CFG_VPD_CAPABILITIES 0x00000040 /* VPD_CAPABILITIES Register */
|
||
|
+#define PCIE_CFG_VPD_DATA 0x00000044 /* VPD_DATA Register */
|
||
|
+#define PCIE_CFG_POWER_MANAGEMENT_CAPABILITY 0x00000048 /* POWER_MANAGEMENT_CAPABILITY Register */
|
||
|
+#define PCIE_CFG_POWER_MANAGEMENT_CONTROL_STATUS 0x0000004c /* POWER_MANAGEMENT_CONTROL_STATUS Register */
|
||
|
+#define PCIE_CFG_MSI_CAPABILITY_HEADER 0x00000050 /* MSI_CAPABILITY_HEADER Register */
|
||
|
+#define PCIE_CFG_MSI_LOWER_ADDRESS 0x00000054 /* MSI_LOWER_ADDRESS Register */
|
||
|
+#define PCIE_CFG_MSI_UPPER_ADDRESS_REGISTER 0x00000058 /* MSI_UPPER_ADDRESS_REGISTER Register */
|
||
|
+#define PCIE_CFG_MSI_DATA 0x0000005c /* MSI_DATA Register */
|
||
|
+#define PCIE_CFG_BROADCOM_VENDOR_SPECIFIC_CAPABILITY_HEADER 0x00000060 /* BROADCOM_VENDOR_SPECIFIC_CAPABILITY_HEADER Register */
|
||
|
+#define PCIE_CFG_RESET_COUNTERS_INITIAL_VALUES 0x00000064 /* RESET_COUNTERS_INITIAL_VALUES Register */
|
||
|
+#define PCIE_CFG_MISCELLANEOUS_HOST_CONTROL 0x00000068 /* MISCELLANEOUS_HOST_CONTROL Register */
|
||
|
+#define PCIE_CFG_SPARE 0x0000006c /* SPARE Register */
|
||
|
+#define PCIE_CFG_PCI_STATE 0x00000070 /* PCI_STATE Register */
|
||
|
+#define PCIE_CFG_CLOCK_CONTROL 0x00000074 /* CLOCK_CONTROL Register */
|
||
|
+#define PCIE_CFG_REGISTER_BASE 0x00000078 /* REGISTER_BASE Register */
|
||
|
+#define PCIE_CFG_MEMORY_BASE 0x0000007c /* MEMORY_BASE Register */
|
||
|
+#define PCIE_CFG_REGISTER_DATA 0x00000080 /* REGISTER_DATA Register */
|
||
|
+#define PCIE_CFG_MEMORY_DATA 0x00000084 /* MEMORY_DATA Register */
|
||
|
+#define PCIE_CFG_EXPANSION_ROM_BAR_SIZE 0x00000088 /* EXPANSION_ROM_BAR_SIZE Register */
|
||
|
+#define PCIE_CFG_EXPANSION_ROM_ADDRESS 0x0000008c /* EXPANSION_ROM_ADDRESS Register */
|
||
|
+#define PCIE_CFG_EXPANSION_ROM_DATA 0x00000090 /* EXPANSION_ROM_DATA Register */
|
||
|
+#define PCIE_CFG_VPD_INTERFACE 0x00000094 /* VPD_INTERFACE Register */
|
||
|
+#define PCIE_CFG_UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_UPPER 0x00000098 /* UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_UPPER Register */
|
||
|
+#define PCIE_CFG_UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_LOWER 0x0000009c /* UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_LOWER Register */
|
||
|
+#define PCIE_CFG_UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_UPPER 0x000000a0 /* UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_UPPER Register */
|
||
|
+#define PCIE_CFG_UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_LOWER 0x000000a4 /* UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_LOWER Register */
|
||
|
+#define PCIE_CFG_UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_UPPER 0x000000a8 /* UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_UPPER Register */
|
||
|
+#define PCIE_CFG_UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_LOWER 0x000000ac /* UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_LOWER Register */
|
||
|
+#define PCIE_CFG_INT_MAILBOX_UPPER 0x000000b0 /* INT_MAILBOX_UPPER Register */
|
||
|
+#define PCIE_CFG_INT_MAILBOX_LOWER 0x000000b4 /* INT_MAILBOX_LOWER Register */
|
||
|
+#define PCIE_CFG_PRODUCT_ID_AND_ASIC_REVISION 0x000000bc /* PRODUCT_ID_AND_ASIC_REVISION Register */
|
||
|
+#define PCIE_CFG_FUNCTION_EVENT 0x000000c0 /* FUNCTION_EVENT Register */
|
||
|
+#define PCIE_CFG_FUNCTION_EVENT_MASK 0x000000c4 /* FUNCTION_EVENT_MASK Register */
|
||
|
+#define PCIE_CFG_FUNCTION_PRESENT 0x000000c8 /* FUNCTION_PRESENT Register */
|
||
|
+#define PCIE_CFG_PCIE_CAPABILITIES 0x000000cc /* PCIE_CAPABILITIES Register */
|
||
|
+#define PCIE_CFG_DEVICE_CAPABILITIES 0x000000d0 /* DEVICE_CAPABILITIES Register */
|
||
|
+#define PCIE_CFG_DEVICE_STATUS_CONTROL 0x000000d4 /* DEVICE_STATUS_CONTROL Register */
|
||
|
+#define PCIE_CFG_LINK_CAPABILITY 0x000000d8 /* LINK_CAPABILITY Register */
|
||
|
+#define PCIE_CFG_LINK_STATUS_CONTROL 0x000000dc /* LINK_STATUS_CONTROL Register */
|
||
|
+#define PCIE_CFG_DEVICE_CAPABILITIES_2 0x000000f0 /* DEVICE_CAPABILITIES_2 Register */
|
||
|
+#define PCIE_CFG_DEVICE_STATUS_CONTROL_2 0x000000f4 /* DEVICE_STATUS_CONTROL_2 Register */
|
||
|
+#define PCIE_CFG_LINK_CAPABILITIES_2 0x000000f8 /* LINK_CAPABILITIES_2 Register */
|
||
|
+#define PCIE_CFG_LINK_STATUS_CONTROL_2 0x000000fc /* LINK_STATUS_CONTROL_2 Register */
|
||
|
+#define PCIE_CFG_ADVANCED_ERROR_REPORTING_ENHANCED_CAPABILITY_HEADER 0x00000100 /* ADVANCED_ERROR_REPORTING_ENHANCED_CAPABILITY_HEADER Register */
|
||
|
+#define PCIE_CFG_UNCORRECTABLE_ERROR_STATUS 0x00000104 /* UNCORRECTABLE_ERROR_STATUS Register */
|
||
|
+#define PCIE_CFG_UNCORRECTABLE_ERROR_MASK 0x00000108 /* UNCORRECTABLE_ERROR_MASK Register */
|
||
|
+#define PCIE_CFG_UNCORRECTABLE_ERROR_SEVERITY 0x0000010c /* UNCORRECTABLE_ERROR_SEVERITY Register */
|
||
|
+#define PCIE_CFG_CORRECTABLE_ERROR_STATUS 0x00000110 /* CORRECTABLE_ERROR_STATUS Register */
|
||
|
+#define PCIE_CFG_CORRECTABLE_ERROR_MASK 0x00000114 /* CORRECTABLE_ERROR_MASK Register */
|
||
|
+#define PCIE_CFG_ADVANCED_ERROR_CAPABILITIES_AND_CONTROL 0x00000118 /* ADVANCED_ERROR_CAPABILITIES_AND_CONTROL Register */
|
||
|
+#define PCIE_CFG_HEADER_LOG_1 0x0000011c /* HEADER_LOG_1 Register */
|
||
|
+#define PCIE_CFG_HEADER_LOG_2 0x00000120 /* HEADER_LOG_2 Register */
|
||
|
+#define PCIE_CFG_HEADER_LOG_3 0x00000124 /* HEADER_LOG_3 Register */
|
||
|
+#define PCIE_CFG_HEADER_LOG_4 0x00000128 /* HEADER_LOG_4 Register */
|
||
|
+#define PCIE_CFG_VIRTUAL_CHANNEL_ENHANCED_CAPABILITY_HEADER 0x0000013c /* VIRTUAL_CHANNEL_ENHANCED_CAPABILITY_HEADER Register */
|
||
|
+#define PCIE_CFG_PORT_VC_CAPABILITY 0x00000140 /* PORT_VC_CAPABILITY Register */
|
||
|
+#define PCIE_CFG_PORT_VC_CAPABILITY_2 0x00000144 /* PORT_VC_CAPABILITY_2 Register */
|
||
|
+#define PCIE_CFG_PORT_VC_STATUS_CONTROL 0x00000148 /* PORT_VC_STATUS_CONTROL Register */
|
||
|
+#define PCIE_CFG_VC_RESOURCE_CAPABILITY 0x0000014c /* VC_RESOURCE_CAPABILITY Register */
|
||
|
+#define PCIE_CFG_VC_RESOURCE_CONTROL 0x00000150 /* VC_RESOURCE_CONTROL Register */
|
||
|
+#define PCIE_CFG_VC_RESOURCE_STATUS 0x00000154 /* VC_RESOURCE_STATUS Register */
|
||
|
+#define PCIE_CFG_DEVICE_SERIAL_NO_ENHANCED_CAPABILITY_HEADER 0x00000160 /* DEVICE_SERIAL_NO_ENHANCED_CAPABILITY_HEADER Register */
|
||
|
+#define PCIE_CFG_DEVICE_SERIAL_NO_LOWER_DW 0x00000164 /* DEVICE_SERIAL_NO_LOWER_DW Register */
|
||
|
+#define PCIE_CFG_DEVICE_SERIAL_NO_UPPER_DW 0x00000168 /* DEVICE_SERIAL_NO_UPPER_DW Register */
|
||
|
+#define PCIE_CFG_POWER_BUDGETING_ENHANCED_CAPABILITY_HEADER 0x0000016c /* POWER_BUDGETING_ENHANCED_CAPABILITY_HEADER Register */
|
||
|
+#define PCIE_CFG_POWER_BUDGETING_DATA_SELECT 0x00000170 /* POWER_BUDGETING_DATA_SELECT Register */
|
||
|
+#define PCIE_CFG_POWER_BUDGETING_DATA 0x00000174 /* POWER_BUDGETING_DATA Register */
|
||
|
+#define PCIE_CFG_POWER_BUDGETING_CAPABILITY 0x00000178 /* POWER_BUDGETING_CAPABILITY Register */
|
||
|
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_2_1 0x0000017c /* FIRMWARE_POWER_BUDGETING_2_1 Register */
|
||
|
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_4_3 0x00000180 /* FIRMWARE_POWER_BUDGETING_4_3 Register */
|
||
|
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_6_5 0x00000184 /* FIRMWARE_POWER_BUDGETING_6_5 Register */
|
||
|
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_8_7 0x00000188 /* FIRMWARE_POWER_BUDGETING_8_7 Register */
|
||
|
+#define PCIE_CFG_PCIE_1_1_ADVISORY_NON_FATAL_ERROR_MASKING 0x0000018c /* PCIE_1_1_ADVISORY_NON_FATAL_ERROR_MASKING Register */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_TGT_TOP_PCIE_TL
|
||
|
+ ***************************************************************************/
|
||
|
+#define PCIE_TL_TL_CONTROL 0x00000400 /* TL_CONTROL Register */
|
||
|
+#define PCIE_TL_TRANSACTION_CONFIGURATION 0x00000404 /* TRANSACTION_CONFIGURATION Register */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_TGT_TOP_PCIE_DLL
|
||
|
+ ***************************************************************************/
|
||
|
+#define PCIE_DLL_DATA_LINK_CONTROL 0x00000500 /* DATA_LINK_CONTROL Register */
|
||
|
+#define PCIE_DLL_DATA_LINK_STATUS 0x00000504 /* DATA_LINK_STATUS Register */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_TGT_TOP_INTR
|
||
|
+ ***************************************************************************/
|
||
|
+#define INTR_INTR_STATUS 0x00000700 /* Interrupt Status Register */
|
||
|
+#define INTR_INTR_SET 0x00000704 /* Interrupt Set Register */
|
||
|
+#define INTR_INTR_CLR_REG 0x00000708 /* Interrupt Clear Register */
|
||
|
+#define INTR_INTR_MSK_STS_REG 0x0000070c /* Interrupt Mask Status Register */
|
||
|
+#define INTR_INTR_MSK_SET_REG 0x00000710 /* Interrupt Mask Set Register */
|
||
|
+#define INTR_INTR_MSK_CLR_REG 0x00000714 /* Interrupt Mask Clear Register */
|
||
|
+#define INTR_EOI_CTRL 0x00000720 /* End of interrupt control register */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_MISC_TOP_MISC1
|
||
|
+ ***************************************************************************/
|
||
|
+#define MISC1_TX_FIRST_DESC_L_ADDR_LIST0 0x00000c00 /* Tx DMA Descriptor List0 First Descriptor lower Address */
|
||
|
+#define MISC1_TX_FIRST_DESC_U_ADDR_LIST0 0x00000c04 /* Tx DMA Descriptor List0 First Descriptor Upper Address */
|
||
|
+#define MISC1_TX_FIRST_DESC_L_ADDR_LIST1 0x00000c08 /* Tx DMA Descriptor List1 First Descriptor Lower Address */
|
||
|
+#define MISC1_TX_FIRST_DESC_U_ADDR_LIST1 0x00000c0c /* Tx DMA Descriptor List1 First Descriptor Upper Address */
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS 0x00000c10 /* Tx DMA Software Descriptor List Control and Status */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS 0x00000c18 /* Tx DMA Engine Error Status */
|
||
|
+#define MISC1_TX_DMA_LIST0_CUR_DESC_L_ADDR 0x00000c1c /* Tx DMA List0 Current Descriptor Lower Address */
|
||
|
+#define MISC1_TX_DMA_LIST0_CUR_DESC_U_ADDR 0x00000c20 /* Tx DMA List0 Current Descriptor Upper Address */
|
||
|
+#define MISC1_TX_DMA_LIST0_CUR_BYTE_CNT_REM 0x00000c24 /* Tx DMA List0 Current Descriptor Upper Address */
|
||
|
+#define MISC1_TX_DMA_LIST1_CUR_DESC_L_ADDR 0x00000c28 /* Tx DMA List1 Current Descriptor Lower Address */
|
||
|
+#define MISC1_TX_DMA_LIST1_CUR_DESC_U_ADDR 0x00000c2c /* Tx DMA List1 Current Descriptor Upper Address */
|
||
|
+#define MISC1_TX_DMA_LIST1_CUR_BYTE_CNT_REM 0x00000c30 /* Tx DMA List1 Current Descriptor Upper Address */
|
||
|
+#define MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0 0x00000c34 /* Y Rx Descriptor List0 First Descriptor Lower Address */
|
||
|
+#define MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST0 0x00000c38 /* Y Rx Descriptor List0 First Descriptor Upper Address */
|
||
|
+#define MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1 0x00000c3c /* Y Rx Descriptor List1 First Descriptor Lower Address */
|
||
|
+#define MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST1 0x00000c40 /* Y Rx Descriptor List1 First Descriptor Upper Address */
|
||
|
+#define MISC1_Y_RX_SW_DESC_LIST_CTRL_STS 0x00000c44 /* Y Rx Software Descriptor List Control and Status */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS 0x00000c4c /* Y Rx Engine Error Status */
|
||
|
+#define MISC1_Y_RX_LIST0_CUR_DESC_L_ADDR 0x00000c50 /* Y Rx List0 Current Descriptor Lower Address */
|
||
|
+#define MISC1_Y_RX_LIST0_CUR_DESC_U_ADDR 0x00000c54 /* Y Rx List0 Current Descriptor Upper Address */
|
||
|
+#define MISC1_Y_RX_LIST0_CUR_BYTE_CNT 0x00000c58 /* Y Rx List0 Current Descriptor Byte Count */
|
||
|
+#define MISC1_Y_RX_LIST1_CUR_DESC_L_ADDR 0x00000c5c /* Y Rx List1 Current Descriptor Lower address */
|
||
|
+#define MISC1_Y_RX_LIST1_CUR_DESC_U_ADDR 0x00000c60 /* Y Rx List1 Current Descriptor Upper address */
|
||
|
+#define MISC1_Y_RX_LIST1_CUR_BYTE_CNT 0x00000c64 /* Y Rx List1 Current Descriptor Byte Count */
|
||
|
+#define MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0 0x00000c68 /* UV Rx Descriptor List0 First Descriptor lower Address */
|
||
|
+#define MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST0 0x00000c6c /* UV Rx Descriptor List0 First Descriptor Upper Address */
|
||
|
+#define MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1 0x00000c70 /* UV Rx Descriptor List1 First Descriptor Lower Address */
|
||
|
+#define MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST1 0x00000c74 /* UV Rx Descriptor List1 First Descriptor Upper Address */
|
||
|
+#define MISC1_UV_RX_SW_DESC_LIST_CTRL_STS 0x00000c78 /* UV Rx Software Descriptor List Control and Status */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS 0x00000c7c /* UV Rx Engine Error Status */
|
||
|
+#define MISC1_UV_RX_LIST0_CUR_DESC_L_ADDR 0x00000c80 /* UV Rx List0 Current Descriptor Lower Address */
|
||
|
+#define MISC1_UV_RX_LIST0_CUR_DESC_U_ADDR 0x00000c84 /* UV Rx List0 Current Descriptor Upper Address */
|
||
|
+#define MISC1_UV_RX_LIST0_CUR_BYTE_CNT 0x00000c88 /* UV Rx List0 Current Descriptor Byte Count */
|
||
|
+#define MISC1_UV_RX_LIST1_CUR_DESC_L_ADDR 0x00000c8c /* UV Rx List1 Current Descriptor Lower Address */
|
||
|
+#define MISC1_UV_RX_LIST1_CUR_DESC_U_ADDR 0x00000c90 /* UV Rx List1 Current Descriptor Upper Address */
|
||
|
+#define MISC1_UV_RX_LIST1_CUR_BYTE_CNT 0x00000c94 /* UV Rx List1 Current Descriptor Byte Count */
|
||
|
+#define MISC1_DMA_DEBUG_OPTIONS_REG 0x00000c98 /* DMA Debug Options Register */
|
||
|
+#define MISC1_READ_CHANNEL_ERROR_STATUS 0x00000c9c /* Read Channel Error Status */
|
||
|
+#define MISC1_PCIE_DMA_CTRL 0x00000ca0 /* PCIE DMA Control Register */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_MISC_TOP_MISC2
|
||
|
+ ***************************************************************************/
|
||
|
+#define MISC2_GLOBAL_CTRL 0x00000d00 /* Global Control Register */
|
||
|
+#define MISC2_INTERNAL_STATUS 0x00000d04 /* Internal Status Register */
|
||
|
+#define MISC2_INTERNAL_STATUS_MUX_CTRL 0x00000d08 /* Internal Debug Mux Control */
|
||
|
+#define MISC2_DEBUG_FIFO_LENGTH 0x00000d0c /* Debug FIFO Length */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_MISC_TOP_MISC3
|
||
|
+ ***************************************************************************/
|
||
|
+#define MISC3_RESET_CTRL 0x00000e00 /* Reset Control Register */
|
||
|
+#define MISC3_BIST_CTRL 0x00000e04 /* BIST Control Register */
|
||
|
+#define MISC3_BIST_STATUS 0x00000e08 /* BIST Status Register */
|
||
|
+#define MISC3_RX_CHECKSUM 0x00000e0c /* Receive Checksum */
|
||
|
+#define MISC3_TX_CHECKSUM 0x00000e10 /* Transmit Checksum */
|
||
|
+#define MISC3_ECO_CTRL_CORE 0x00000e14 /* ECO Core Reset Control Register */
|
||
|
+#define MISC3_CSI_TEST_CTRL 0x00000e18 /* CSI Test Control Register */
|
||
|
+#define MISC3_HD_DVI_TEST_CTRL 0x00000e1c /* HD DVI Test Control Register */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_MISC_TOP_MISC_PERST
|
||
|
+ ***************************************************************************/
|
||
|
+#define MISC_PERST_ECO_CTRL_PERST 0x00000e80 /* ECO PCIE Reset Control Register */
|
||
|
+#define MISC_PERST_DECODER_CTRL 0x00000e84 /* Decoder Control Register */
|
||
|
+#define MISC_PERST_CCE_STATUS 0x00000e88 /* Config Copy Engine Status */
|
||
|
+#define MISC_PERST_PCIE_DEBUG 0x00000e8c /* PCIE Debug Control Register */
|
||
|
+#define MISC_PERST_PCIE_DEBUG_STATUS 0x00000e90 /* PCIE Debug Status Register */
|
||
|
+#define MISC_PERST_VREG_CTRL 0x00000e94 /* Voltage Regulator Control Register */
|
||
|
+#define MISC_PERST_MEM_CTRL 0x00000e98 /* Memory Control Register */
|
||
|
+#define MISC_PERST_CLOCK_CTRL 0x00000e9c /* Clock Control Register */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_MISC_TOP_GISB_ARBITER
|
||
|
+ ***************************************************************************/
|
||
|
+#define GISB_ARBITER_REVISION 0x00000f00 /* GISB ARBITER REVISION */
|
||
|
+#define GISB_ARBITER_SCRATCH 0x00000f04 /* GISB ARBITER Scratch Register */
|
||
|
+#define GISB_ARBITER_REQ_MASK 0x00000f08 /* GISB ARBITER Master Request Mask Register */
|
||
|
+#define GISB_ARBITER_TIMER 0x00000f0c /* GISB ARBITER Timer Value Register */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_OTP_TOP_OTP
|
||
|
+ ***************************************************************************/
|
||
|
+#define OTP_CONFIG_INFO 0x00001400 /* OTP Configuration Register */
|
||
|
+#define OTP_CMD 0x00001404 /* OTP Command Register */
|
||
|
+#define OTP_STATUS 0x00001408 /* OTP Status Register */
|
||
|
+#define OTP_CONTENT_MISC 0x0000140c /* Content : Miscellaneous Register */
|
||
|
+#define OTP_CONTENT_AES_0 0x00001410 /* Content : AES Key 0 Register */
|
||
|
+#define OTP_CONTENT_AES_1 0x00001414 /* Content : AES Key 1 Register */
|
||
|
+#define OTP_CONTENT_AES_2 0x00001418 /* Content : AES Key 2 Register */
|
||
|
+#define OTP_CONTENT_AES_3 0x0000141c /* Content : AES Key 3 Register */
|
||
|
+#define OTP_CONTENT_SHA_0 0x00001420 /* Content : SHA Key 0 Register */
|
||
|
+#define OTP_CONTENT_SHA_1 0x00001424 /* Content : SHA Key 1 Register */
|
||
|
+#define OTP_CONTENT_SHA_2 0x00001428 /* Content : SHA Key 2 Register */
|
||
|
+#define OTP_CONTENT_SHA_3 0x0000142c /* Content : SHA Key 3 Register */
|
||
|
+#define OTP_CONTENT_SHA_4 0x00001430 /* Content : SHA Key 4 Register */
|
||
|
+#define OTP_CONTENT_SHA_5 0x00001434 /* Content : SHA Key 5 Register */
|
||
|
+#define OTP_CONTENT_SHA_6 0x00001438 /* Content : SHA Key 6 Register */
|
||
|
+#define OTP_CONTENT_SHA_7 0x0000143c /* Content : SHA Key 7 Register */
|
||
|
+#define OTP_CONTENT_CHECKSUM 0x00001440 /* Content : Checksum Register */
|
||
|
+#define OTP_PROG_CTRL 0x00001444 /* Programming Control Register */
|
||
|
+#define OTP_PROG_STATUS 0x00001448 /* Programming Status Register */
|
||
|
+#define OTP_PROG_PULSE 0x0000144c /* Program Pulse Width Register */
|
||
|
+#define OTP_VERIFY_PULSE 0x00001450 /* Verify Pulse Width Register */
|
||
|
+#define OTP_PROG_MASK 0x00001454 /* Program Mask Register */
|
||
|
+#define OTP_DATA_INPUT 0x00001458 /* Data Input Register */
|
||
|
+#define OTP_DATA_OUTPUT 0x0000145c /* Data Output Register */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_AES_TOP_AES
|
||
|
+ ***************************************************************************/
|
||
|
+#define AES_CONFIG_INFO 0x00001800 /* AES Configuration Information Register */
|
||
|
+#define AES_CMD 0x00001804 /* AES Command Register */
|
||
|
+#define AES_STATUS 0x00001808 /* AES Status Register */
|
||
|
+#define AES_EEPROM_CONFIG 0x0000180c /* AES EEPROM Configuration Register */
|
||
|
+#define AES_EEPROM_DATA_0 0x00001810 /* AES EEPROM Data Register 0 */
|
||
|
+#define AES_EEPROM_DATA_1 0x00001814 /* AES EEPROM Data Register 1 */
|
||
|
+#define AES_EEPROM_DATA_2 0x00001818 /* AES EEPROM Data Register 2 */
|
||
|
+#define AES_EEPROM_DATA_3 0x0000181c /* AES EEPROM Data Register 3 */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_DCI_TOP_DCI
|
||
|
+ ***************************************************************************/
|
||
|
+#define DCI_CMD 0x00001c00 /* DCI Command Register */
|
||
|
+#define DCI_STATUS 0x00001c04 /* DCI Status Register */
|
||
|
+#define DCI_DRAM_BASE_ADDR 0x00001c08 /* DRAM Base Address Register */
|
||
|
+#define DCI_FIRMWARE_ADDR 0x00001c0c /* Firmware Address Register */
|
||
|
+#define DCI_FIRMWARE_DATA 0x00001c10 /* Firmware Data Register */
|
||
|
+#define DCI_SIGNATURE_DATA_0 0x00001c14 /* Signature Data Register 0 */
|
||
|
+#define DCI_SIGNATURE_DATA_1 0x00001c18 /* Signature Data Register 1 */
|
||
|
+#define DCI_SIGNATURE_DATA_2 0x00001c1c /* Signature Data Register 2 */
|
||
|
+#define DCI_SIGNATURE_DATA_3 0x00001c20 /* Signature Data Register 3 */
|
||
|
+#define DCI_SIGNATURE_DATA_4 0x00001c24 /* Signature Data Register 4 */
|
||
|
+#define DCI_SIGNATURE_DATA_5 0x00001c28 /* Signature Data Register 5 */
|
||
|
+#define DCI_SIGNATURE_DATA_6 0x00001c2c /* Signature Data Register 6 */
|
||
|
+#define DCI_SIGNATURE_DATA_7 0x00001c30 /* Signature Data Register 7 */
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * BCM70012_TGT_TOP_INTR
|
||
|
+ ***************************************************************************/
|
||
|
+/****************************************************************************
|
||
|
+ * INTR :: INTR_STATUS
|
||
|
+ ***************************************************************************/
|
||
|
+/* INTR :: INTR_STATUS :: reserved0 [31:26] */
|
||
|
+#define INTR_INTR_STATUS_reserved0_MASK 0xfc000000
|
||
|
+#define INTR_INTR_STATUS_reserved0_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_reserved0_BITS 6
|
||
|
+#define INTR_INTR_STATUS_reserved0_SHIFT 26
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: PCIE_TGT_CA_ATTN [25:25] */
|
||
|
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_MASK 0x02000000
|
||
|
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_BITS 1
|
||
|
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_SHIFT 25
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: PCIE_TGT_UR_ATTN [24:24] */
|
||
|
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_MASK 0x01000000
|
||
|
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_BITS 1
|
||
|
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_SHIFT 24
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: reserved1 [23:14] */
|
||
|
+#define INTR_INTR_STATUS_reserved1_MASK 0x00ffc000
|
||
|
+#define INTR_INTR_STATUS_reserved1_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_reserved1_BITS 10
|
||
|
+#define INTR_INTR_STATUS_reserved1_SHIFT 14
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L1_UV_RX_DMA_ERR_INTR [13:13] */
|
||
|
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_MASK 0x00002000
|
||
|
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_SHIFT 13
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L1_UV_RX_DMA_DONE_INTR [12:12] */
|
||
|
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK 0x00001000
|
||
|
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_SHIFT 12
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L1_Y_RX_DMA_ERR_INTR [11:11] */
|
||
|
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_MASK 0x00000800
|
||
|
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_SHIFT 11
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L1_Y_RX_DMA_DONE_INTR [10:10] */
|
||
|
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK 0x00000400
|
||
|
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_SHIFT 10
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L1_TX_DMA_ERR_INTR [09:09] */
|
||
|
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_MASK 0x00000200
|
||
|
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_SHIFT 9
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L1_TX_DMA_DONE_INTR [08:08] */
|
||
|
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_MASK 0x00000100
|
||
|
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_SHIFT 8
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: reserved2 [07:06] */
|
||
|
+#define INTR_INTR_STATUS_reserved2_MASK 0x000000c0
|
||
|
+#define INTR_INTR_STATUS_reserved2_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_reserved2_BITS 2
|
||
|
+#define INTR_INTR_STATUS_reserved2_SHIFT 6
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L0_UV_RX_DMA_ERR_INTR [05:05] */
|
||
|
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_MASK 0x00000020
|
||
|
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_SHIFT 5
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L0_UV_RX_DMA_DONE_INTR [04:04] */
|
||
|
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK 0x00000010
|
||
|
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_SHIFT 4
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L0_Y_RX_DMA_ERR_INTR [03:03] */
|
||
|
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_MASK 0x00000008
|
||
|
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_SHIFT 3
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L0_Y_RX_DMA_DONE_INTR [02:02] */
|
||
|
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK 0x00000004
|
||
|
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_SHIFT 2
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L0_TX_DMA_ERR_INTR [01:01] */
|
||
|
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_MASK 0x00000002
|
||
|
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_SHIFT 1
|
||
|
+
|
||
|
+/* INTR :: INTR_STATUS :: L0_TX_DMA_DONE_INTR [00:00] */
|
||
|
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_MASK 0x00000001
|
||
|
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_ALIGN 0
|
||
|
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_BITS 1
|
||
|
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_SHIFT 0
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * MISC1 :: TX_SW_DESC_LIST_CTRL_STS
|
||
|
+ ***************************************************************************/
|
||
|
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: reserved0 [31:04] */
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_MASK 0xfffffff0
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_ALIGN 0
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_BITS 28
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_SHIFT 4
|
||
|
+
|
||
|
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: DMA_DATA_SERV_PTR [03:03] */
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_MASK 0x00000008
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_ALIGN 0
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_BITS 1
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_SHIFT 3
|
||
|
+
|
||
|
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: DESC_SERV_PTR [02:02] */
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_MASK 0x00000004
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_ALIGN 0
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_BITS 1
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_SHIFT 2
|
||
|
+
|
||
|
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: TX_DMA_HALT_ON_ERROR [01:01] */
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_MASK 0x00000002
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_ALIGN 0
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_BITS 1
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_SHIFT 1
|
||
|
+
|
||
|
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: TX_DMA_RUN_STOP [00:00] */
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_MASK 0x00000001
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_ALIGN 0
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_BITS 1
|
||
|
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_SHIFT 0
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * MISC1 :: TX_DMA_ERROR_STATUS
|
||
|
+ ***************************************************************************/
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved0 [31:10] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_MASK 0xfffffc00
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_BITS 22
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_SHIFT 10
|
||
|
+
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_DESC_TX_ABORT_ERRORS [09:09] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_MASK 0x00000200
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_BITS 1
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_SHIFT 9
|
||
|
+
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved1 [08:08] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_MASK 0x00000100
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_BITS 1
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_SHIFT 8
|
||
|
+
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_DESC_TX_ABORT_ERRORS [07:07] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_MASK 0x00000080
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_BITS 1
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_SHIFT 7
|
||
|
+
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved2 [06:06] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_MASK 0x00000040
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_BITS 1
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_SHIFT 6
|
||
|
+
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_DMA_DATA_TX_ABORT_ERRORS [05:05] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_MASK 0x00000020
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_BITS 1
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_SHIFT 5
|
||
|
+
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_FIFO_FULL_ERRORS [04:04] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK 0x00000010
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_BITS 1
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_SHIFT 4
|
||
|
+
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved3 [03:03] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_MASK 0x00000008
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_BITS 1
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_SHIFT 3
|
||
|
+
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_DMA_DATA_TX_ABORT_ERRORS [02:02] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_MASK 0x00000004
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_BITS 1
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_SHIFT 2
|
||
|
+
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_FIFO_FULL_ERRORS [01:01] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK 0x00000002
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_BITS 1
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_SHIFT 1
|
||
|
+
|
||
|
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved4 [00:00] */
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_MASK 0x00000001
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_ALIGN 0
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_BITS 1
|
||
|
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_SHIFT 0
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * MISC1 :: Y_RX_ERROR_STATUS
|
||
|
+ ***************************************************************************/
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved0 [31:14] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_MASK 0xffffc000
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_BITS 18
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_SHIFT 14
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_UNDERRUN_ERROR [13:13] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK 0x00002000
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_BITS 1
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_SHIFT 13
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_OVERRUN_ERROR [12:12] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK 0x00001000
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_BITS 1
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_SHIFT 12
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_UNDERRUN_ERROR [11:11] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK 0x00000800
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_BITS 1
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_SHIFT 11
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_OVERRUN_ERROR [10:10] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK 0x00000400
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_BITS 1
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_SHIFT 10
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_DESC_TX_ABORT_ERRORS [09:09] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK 0x00000200
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_BITS 1
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_SHIFT 9
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved1 [08:08] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_MASK 0x00000100
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_BITS 1
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_SHIFT 8
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_DESC_TX_ABORT_ERRORS [07:07] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK 0x00000080
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_BITS 1
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_SHIFT 7
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved2 [06:05] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_MASK 0x00000060
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_BITS 2
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_SHIFT 5
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_FIFO_FULL_ERRORS [04:04] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK 0x00000010
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_BITS 1
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_SHIFT 4
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved3 [03:02] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_MASK 0x0000000c
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_BITS 2
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_SHIFT 2
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_FIFO_FULL_ERRORS [01:01] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK 0x00000002
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_BITS 1
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_SHIFT 1
|
||
|
+
|
||
|
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved4 [00:00] */
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_MASK 0x00000001
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_ALIGN 0
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_BITS 1
|
||
|
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_SHIFT 0
|
||
|
+
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * MISC1 :: UV_RX_ERROR_STATUS
|
||
|
+ ***************************************************************************/
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved0 [31:14] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_MASK 0xffffc000
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_BITS 18
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_SHIFT 14
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_UNDERRUN_ERROR [13:13] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK 0x00002000
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_BITS 1
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_SHIFT 13
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_OVERRUN_ERROR [12:12] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK 0x00001000
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_BITS 1
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_SHIFT 12
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_UNDERRUN_ERROR [11:11] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK 0x00000800
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_BITS 1
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_SHIFT 11
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_OVERRUN_ERROR [10:10] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK 0x00000400
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_BITS 1
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_SHIFT 10
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_DESC_TX_ABORT_ERRORS [09:09] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK 0x00000200
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_BITS 1
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_SHIFT 9
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved1 [08:08] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_MASK 0x00000100
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_BITS 1
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_SHIFT 8
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_DESC_TX_ABORT_ERRORS [07:07] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK 0x00000080
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_BITS 1
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_SHIFT 7
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved2 [06:05] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_MASK 0x00000060
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_BITS 2
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_SHIFT 5
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_FIFO_FULL_ERRORS [04:04] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK 0x00000010
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_BITS 1
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_SHIFT 4
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved3 [03:02] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_MASK 0x0000000c
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_BITS 2
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_SHIFT 2
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_FIFO_FULL_ERRORS [01:01] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK 0x00000002
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_BITS 1
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_SHIFT 1
|
||
|
+
|
||
|
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved4 [00:00] */
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_MASK 0x00000001
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_ALIGN 0
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_BITS 1
|
||
|
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_SHIFT 0
|
||
|
+
|
||
|
+/****************************************************************************
|
||
|
+ * Datatype Definitions.
|
||
|
+ ***************************************************************************/
|
||
|
+#endif /* #ifndef MACFILE_H__ */
|
||
|
+
|
||
|
+/* End of File */
|
||
|
+
|
||
|
diff --git a/drivers/staging/crystalhd/crystalhd_cmds.c b/drivers/staging/crystalhd/crystalhd_cmds.c
|
||
|
new file mode 100644
|
||
|
index 0000000..39c641d
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/crystalhd_cmds.c
|
||
|
@@ -0,0 +1,1058 @@
|
||
|
+/***************************************************************************
|
||
|
+ * Copyright (c) 2005-2009, Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: crystalhd_cmds . c
|
||
|
+ *
|
||
|
+ * Description:
|
||
|
+ * BCM70010 Linux driver user command interfaces.
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ **********************************************************************
|
||
|
+ * This file is part of the crystalhd device driver.
|
||
|
+ *
|
||
|
+ * This driver is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, version 2 of the License.
|
||
|
+ *
|
||
|
+ * This driver is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this driver. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ **********************************************************************/
|
||
|
+
|
||
|
+#include "crystalhd_cmds.h"
|
||
|
+#include "crystalhd_hw.h"
|
||
|
+
|
||
|
+static struct crystalhd_user *bc_cproc_get_uid(struct crystalhd_cmd *ctx)
|
||
|
+{
|
||
|
+ struct crystalhd_user *user = NULL;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
|
||
|
+ if (!ctx->user[i].in_use) {
|
||
|
+ user = &ctx->user[i];
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return user;
|
||
|
+}
|
||
|
+
|
||
|
+static int bc_cproc_get_user_count(struct crystalhd_cmd *ctx)
|
||
|
+{
|
||
|
+ int i, count = 0;
|
||
|
+
|
||
|
+ for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
|
||
|
+ if (ctx->user[i].in_use)
|
||
|
+ count++;
|
||
|
+ }
|
||
|
+
|
||
|
+ return count;
|
||
|
+}
|
||
|
+
|
||
|
+static void bc_cproc_mark_pwr_state(struct crystalhd_cmd *ctx)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
|
||
|
+ if (!ctx->user[i].in_use)
|
||
|
+ continue;
|
||
|
+ if (ctx->user[i].mode == DTS_DIAG_MODE ||
|
||
|
+ ctx->user[i].mode == DTS_PLAYBACK_MODE) {
|
||
|
+ ctx->pwr_state_change = 1;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_notify_mode(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ int rc = 0, i = 0;
|
||
|
+
|
||
|
+ if (!ctx || !idata) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (ctx->user[idata->u_id].mode != DTS_MODE_INV) {
|
||
|
+ BCMLOG_ERR("Close the handle first..\n");
|
||
|
+ return BC_STS_ERR_USAGE;
|
||
|
+ }
|
||
|
+ if (idata->udata.u.NotifyMode.Mode == DTS_MONITOR_MODE) {
|
||
|
+ ctx->user[idata->u_id].mode = idata->udata.u.NotifyMode.Mode;
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+ }
|
||
|
+ if (ctx->state != BC_LINK_INVALID) {
|
||
|
+ BCMLOG_ERR("Link invalid state %d \n", ctx->state);
|
||
|
+ return BC_STS_ERR_USAGE;
|
||
|
+ }
|
||
|
+ /* Check for duplicate playback sessions..*/
|
||
|
+ for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
|
||
|
+ if (ctx->user[i].mode == DTS_DIAG_MODE ||
|
||
|
+ ctx->user[i].mode == DTS_PLAYBACK_MODE) {
|
||
|
+ BCMLOG_ERR("multiple playback sessions are not "
|
||
|
+ "supported..\n");
|
||
|
+ return BC_STS_ERR_USAGE;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ ctx->cin_wait_exit = 0;
|
||
|
+ ctx->user[idata->u_id].mode = idata->udata.u.NotifyMode.Mode;
|
||
|
+ /* Setup mmap pool for uaddr sgl mapping..*/
|
||
|
+ rc = crystalhd_create_dio_pool(ctx->adp, BC_LINK_MAX_SGLS);
|
||
|
+ if (rc)
|
||
|
+ return BC_STS_ERROR;
|
||
|
+
|
||
|
+ /* Setup Hardware DMA rings */
|
||
|
+ return crystalhd_hw_setup_dma_rings(&ctx->hw_ctx);
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_get_version(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+
|
||
|
+ if (!ctx || !idata) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+ idata->udata.u.VerInfo.DriverMajor = crystalhd_kmod_major;
|
||
|
+ idata->udata.u.VerInfo.DriverMinor = crystalhd_kmod_minor;
|
||
|
+ idata->udata.u.VerInfo.DriverRevision = crystalhd_kmod_rev;
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_get_hwtype(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ if (!ctx || !idata) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_pci_cfg_rd(ctx->adp, 0, 2,
|
||
|
+ (uint32_t *)&idata->udata.u.hwType.PciVenId);
|
||
|
+ crystalhd_pci_cfg_rd(ctx->adp, 2, 2,
|
||
|
+ (uint32_t *)&idata->udata.u.hwType.PciDevId);
|
||
|
+ crystalhd_pci_cfg_rd(ctx->adp, 8, 1,
|
||
|
+ (uint32_t *)&idata->udata.u.hwType.HwRev);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_reg_rd(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ if (!ctx || !idata)
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ idata->udata.u.regAcc.Value = bc_dec_reg_rd(ctx->adp,
|
||
|
+ idata->udata.u.regAcc.Offset);
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_reg_wr(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ if (!ctx || !idata)
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+
|
||
|
+ bc_dec_reg_wr(ctx->adp, idata->udata.u.regAcc.Offset,
|
||
|
+ idata->udata.u.regAcc.Value);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_link_reg_rd(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ if (!ctx || !idata)
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+
|
||
|
+ idata->udata.u.regAcc.Value = crystalhd_reg_rd(ctx->adp,
|
||
|
+ idata->udata.u.regAcc.Offset);
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_link_reg_wr(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ if (!ctx || !idata)
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+
|
||
|
+ crystalhd_reg_wr(ctx->adp, idata->udata.u.regAcc.Offset,
|
||
|
+ idata->udata.u.regAcc.Value);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_mem_rd(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (!ctx || !idata || !idata->add_cdata)
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+
|
||
|
+ if (idata->udata.u.devMem.NumDwords > (idata->add_cdata_sz / 4)) {
|
||
|
+ BCMLOG_ERR("insufficient buffer\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+ sts = crystalhd_mem_rd(ctx->adp, idata->udata.u.devMem.StartOff,
|
||
|
+ idata->udata.u.devMem.NumDwords,
|
||
|
+ (uint32_t *)idata->add_cdata);
|
||
|
+ return sts;
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_mem_wr(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (!ctx || !idata || !idata->add_cdata)
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+
|
||
|
+ if (idata->udata.u.devMem.NumDwords > (idata->add_cdata_sz / 4)) {
|
||
|
+ BCMLOG_ERR("insufficient buffer\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_mem_wr(ctx->adp, idata->udata.u.devMem.StartOff,
|
||
|
+ idata->udata.u.devMem.NumDwords,
|
||
|
+ (uint32_t *)idata->add_cdata);
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_cfg_rd(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ uint32_t ix, cnt, off, len;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ uint32_t *temp;
|
||
|
+
|
||
|
+ if (!ctx || !idata)
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+
|
||
|
+ temp = (uint32_t *) idata->udata.u.pciCfg.pci_cfg_space;
|
||
|
+ off = idata->udata.u.pciCfg.Offset;
|
||
|
+ len = idata->udata.u.pciCfg.Size;
|
||
|
+
|
||
|
+ if (len <= 4)
|
||
|
+ return crystalhd_pci_cfg_rd(ctx->adp, off, len, temp);
|
||
|
+
|
||
|
+ /* Truncate to dword alignment..*/
|
||
|
+ len = 4;
|
||
|
+ cnt = idata->udata.u.pciCfg.Size / len;
|
||
|
+ for (ix = 0; ix < cnt; ix++) {
|
||
|
+ sts = crystalhd_pci_cfg_rd(ctx->adp, off, len, &temp[ix]);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("config read : %d\n", sts);
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+ off += len;
|
||
|
+ }
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_cfg_wr(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ uint32_t ix, cnt, off, len;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ uint32_t *temp;
|
||
|
+
|
||
|
+ if (!ctx || !idata)
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+
|
||
|
+ temp = (uint32_t *) idata->udata.u.pciCfg.pci_cfg_space;
|
||
|
+ off = idata->udata.u.pciCfg.Offset;
|
||
|
+ len = idata->udata.u.pciCfg.Size;
|
||
|
+
|
||
|
+ if (len <= 4)
|
||
|
+ return crystalhd_pci_cfg_wr(ctx->adp, off, len, temp[0]);
|
||
|
+
|
||
|
+ /* Truncate to dword alignment..*/
|
||
|
+ len = 4;
|
||
|
+ cnt = idata->udata.u.pciCfg.Size / len;
|
||
|
+ for (ix = 0; ix < cnt; ix++) {
|
||
|
+ sts = crystalhd_pci_cfg_wr(ctx->adp, off, len, temp[ix]);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("config write : %d\n", sts);
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+ off += len;
|
||
|
+ }
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_download_fw(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (!ctx || !idata || !idata->add_cdata || !idata->add_cdata_sz) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (ctx->state != BC_LINK_INVALID) {
|
||
|
+ BCMLOG_ERR("Link invalid state %d \n", ctx->state);
|
||
|
+ return BC_STS_ERR_USAGE;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_download_fw(ctx->adp, (uint8_t *)idata->add_cdata,
|
||
|
+ idata->add_cdata_sz);
|
||
|
+
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("Firmware Download Failure!! - %d\n", sts);
|
||
|
+ } else
|
||
|
+ ctx->state |= BC_LINK_INIT;
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * We use the FW_CMD interface to sync up playback state with application
|
||
|
+ * and firmware. This function will perform the required pre and post
|
||
|
+ * processing of the Firmware commands.
|
||
|
+ *
|
||
|
+ * Pause -
|
||
|
+ * Disable capture after decoder pause.
|
||
|
+ * Resume -
|
||
|
+ * First enable capture and issue decoder resume command.
|
||
|
+ * Flush -
|
||
|
+ * Abort pending input transfers and issue decoder flush command.
|
||
|
+ *
|
||
|
+ */
|
||
|
+static BC_STATUS bc_cproc_do_fw_cmd(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ BC_STATUS sts;
|
||
|
+ uint32_t *cmd;
|
||
|
+
|
||
|
+ if (!(ctx->state & BC_LINK_INIT)) {
|
||
|
+ BCMLOG_ERR("Link invalid state %d \n", ctx->state);
|
||
|
+ return BC_STS_ERR_USAGE;
|
||
|
+ }
|
||
|
+
|
||
|
+ cmd = idata->udata.u.fwCmd.cmd;
|
||
|
+
|
||
|
+ /* Pre-Process */
|
||
|
+ if (cmd[0] == eCMD_C011_DEC_CHAN_PAUSE) {
|
||
|
+ if (!cmd[3]) {
|
||
|
+ ctx->state &= ~BC_LINK_PAUSED;
|
||
|
+ crystalhd_hw_unpause(&ctx->hw_ctx);
|
||
|
+ }
|
||
|
+ } else if (cmd[0] == eCMD_C011_DEC_CHAN_FLUSH) {
|
||
|
+ BCMLOG(BCMLOG_INFO, "Flush issued\n");
|
||
|
+ if (cmd[3])
|
||
|
+ ctx->cin_wait_exit = 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_do_fw_cmd(&ctx->hw_ctx, &idata->udata.u.fwCmd);
|
||
|
+
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG(BCMLOG_INFO, "fw cmd %x failed\n", cmd[0]);
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Post-Process */
|
||
|
+ if (cmd[0] == eCMD_C011_DEC_CHAN_PAUSE) {
|
||
|
+ if (cmd[3]) {
|
||
|
+ ctx->state |= BC_LINK_PAUSED;
|
||
|
+ crystalhd_hw_pause(&ctx->hw_ctx);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+static void bc_proc_in_completion(crystalhd_dio_req *dio_hnd,
|
||
|
+ wait_queue_head_t *event, BC_STATUS sts)
|
||
|
+{
|
||
|
+ if (!dio_hnd || !event) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ if (sts == BC_STS_IO_USER_ABORT)
|
||
|
+ return;
|
||
|
+
|
||
|
+ dio_hnd->uinfo.comp_sts = sts;
|
||
|
+ dio_hnd->uinfo.ev_sts = 1;
|
||
|
+ crystalhd_set_event(event);
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_codein_sleep(struct crystalhd_cmd *ctx)
|
||
|
+{
|
||
|
+ wait_queue_head_t sleep_ev;
|
||
|
+ int rc = 0;
|
||
|
+
|
||
|
+ if (ctx->state & BC_LINK_SUSPEND)
|
||
|
+ return BC_STS_IO_USER_ABORT;
|
||
|
+
|
||
|
+ if (ctx->cin_wait_exit) {
|
||
|
+ ctx->cin_wait_exit = 0;
|
||
|
+ return BC_STS_CMD_CANCELLED;
|
||
|
+ }
|
||
|
+ crystalhd_create_event(&sleep_ev);
|
||
|
+ crystalhd_wait_on_event(&sleep_ev, 0, 100, rc, 0);
|
||
|
+ if (rc == -EINTR)
|
||
|
+ return BC_STS_IO_USER_ABORT;
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_hw_txdma(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata,
|
||
|
+ crystalhd_dio_req *dio)
|
||
|
+{
|
||
|
+ uint32_t tx_listid = 0;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ wait_queue_head_t event;
|
||
|
+ int rc = 0;
|
||
|
+
|
||
|
+ if (!ctx || !idata || !dio) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_create_event(&event);
|
||
|
+
|
||
|
+ ctx->tx_list_id = 0;
|
||
|
+ /* msleep_interruptible(2000); */
|
||
|
+ sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio, bc_proc_in_completion,
|
||
|
+ &event, &tx_listid,
|
||
|
+ idata->udata.u.ProcInput.Encrypted);
|
||
|
+
|
||
|
+ while (sts == BC_STS_BUSY) {
|
||
|
+ sts = bc_cproc_codein_sleep(ctx);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ break;
|
||
|
+ sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio,
|
||
|
+ bc_proc_in_completion,
|
||
|
+ &event, &tx_listid,
|
||
|
+ idata->udata.u.ProcInput.Encrypted);
|
||
|
+ }
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG(BCMLOG_DBG, "_hw_txdma returning sts:%d\n", sts);
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+ if (ctx->cin_wait_exit)
|
||
|
+ ctx->cin_wait_exit = 0;
|
||
|
+
|
||
|
+ ctx->tx_list_id = tx_listid;
|
||
|
+
|
||
|
+ /* _post() succeeded.. wait for the completion. */
|
||
|
+ crystalhd_wait_on_event(&event, (dio->uinfo.ev_sts), 3000, rc, 0);
|
||
|
+ ctx->tx_list_id = 0;
|
||
|
+ if (!rc) {
|
||
|
+ return dio->uinfo.comp_sts;
|
||
|
+ } else if (rc == -EBUSY) {
|
||
|
+ BCMLOG(BCMLOG_DBG, "_tx_post() T/O \n");
|
||
|
+ sts = BC_STS_TIMEOUT;
|
||
|
+ } else if (rc == -EINTR) {
|
||
|
+ BCMLOG(BCMLOG_DBG, "Tx Wait Signal int.\n");
|
||
|
+ sts = BC_STS_IO_USER_ABORT;
|
||
|
+ } else {
|
||
|
+ sts = BC_STS_IO_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* We are cancelling the IO from the same context as the _post().
|
||
|
+ * so no need to wait on the event again.. the return itself
|
||
|
+ * ensures the release of our resources.
|
||
|
+ */
|
||
|
+ crystalhd_hw_cancel_tx(&ctx->hw_ctx, tx_listid);
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+/* Helper function to check on user buffers */
|
||
|
+static BC_STATUS bc_cproc_check_inbuffs(bool pin, void *ubuff, uint32_t ub_sz,
|
||
|
+ uint32_t uv_off, bool en_422)
|
||
|
+{
|
||
|
+ if (!ubuff || !ub_sz) {
|
||
|
+ BCMLOG_ERR("%s->Invalid Arg %p %x\n",
|
||
|
+ ((pin) ? "TX" : "RX"), ubuff, ub_sz);
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Check for alignment */
|
||
|
+ if (((uintptr_t)ubuff) & 0x03) {
|
||
|
+ BCMLOG_ERR("%s-->Un-aligned address not implemented yet.. %p \n",
|
||
|
+ ((pin) ? "TX" : "RX"), ubuff);
|
||
|
+ return BC_STS_NOT_IMPL;
|
||
|
+ }
|
||
|
+ if (pin)
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (!en_422 && !uv_off) {
|
||
|
+ BCMLOG_ERR("Need UV offset for 420 mode.\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (en_422 && uv_off) {
|
||
|
+ BCMLOG_ERR("UV offset in 422 mode ??\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_proc_input(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ void *ubuff;
|
||
|
+ uint32_t ub_sz;
|
||
|
+ crystalhd_dio_req *dio_hnd = NULL;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (!ctx || !idata) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ ubuff = idata->udata.u.ProcInput.pDmaBuff;
|
||
|
+ ub_sz = idata->udata.u.ProcInput.BuffSz;
|
||
|
+
|
||
|
+ sts = bc_cproc_check_inbuffs(1, ubuff, ub_sz, 0, 0);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ return sts;
|
||
|
+
|
||
|
+ sts = crystalhd_map_dio(ctx->adp, ubuff, ub_sz, 0, 0, 1, &dio_hnd);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("dio map - %d \n", sts);
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!dio_hnd)
|
||
|
+ return BC_STS_ERROR;
|
||
|
+
|
||
|
+ sts = bc_cproc_hw_txdma(ctx, idata, dio_hnd);
|
||
|
+
|
||
|
+ crystalhd_unmap_dio(ctx->adp, dio_hnd);
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_add_cap_buff(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ void *ubuff;
|
||
|
+ uint32_t ub_sz, uv_off;
|
||
|
+ bool en_422;
|
||
|
+ crystalhd_dio_req *dio_hnd = NULL;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (!ctx || !idata) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ ubuff = idata->udata.u.RxBuffs.YuvBuff;
|
||
|
+ ub_sz = idata->udata.u.RxBuffs.YuvBuffSz;
|
||
|
+ uv_off = idata->udata.u.RxBuffs.UVbuffOffset;
|
||
|
+ en_422 = idata->udata.u.RxBuffs.b422Mode;
|
||
|
+
|
||
|
+ sts = bc_cproc_check_inbuffs(0, ubuff, ub_sz, uv_off, en_422);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ return sts;
|
||
|
+
|
||
|
+ sts = crystalhd_map_dio(ctx->adp, ubuff, ub_sz, uv_off,
|
||
|
+ en_422, 0, &dio_hnd);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("dio map - %d \n", sts);
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!dio_hnd)
|
||
|
+ return BC_STS_ERROR;
|
||
|
+
|
||
|
+ sts = crystalhd_hw_add_cap_buffer(&ctx->hw_ctx, dio_hnd, (ctx->state == BC_LINK_READY));
|
||
|
+ if ((sts != BC_STS_SUCCESS) && (sts != BC_STS_BUSY)) {
|
||
|
+ crystalhd_unmap_dio(ctx->adp, dio_hnd);
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_fmt_change(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_dio_req *dio)
|
||
|
+{
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ sts = crystalhd_hw_add_cap_buffer(&ctx->hw_ctx, dio, 0);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ return sts;
|
||
|
+
|
||
|
+ ctx->state |= BC_LINK_FMT_CHG;
|
||
|
+ if (ctx->state == BC_LINK_READY)
|
||
|
+ sts = crystalhd_hw_start_capture(&ctx->hw_ctx);
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_fetch_frame(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ crystalhd_dio_req *dio = NULL;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ BC_DEC_OUT_BUFF *frame;
|
||
|
+
|
||
|
+ if (!ctx || !idata) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!(ctx->state & BC_LINK_CAP_EN)) {
|
||
|
+ BCMLOG(BCMLOG_DBG, "Capture not enabled..%x\n", ctx->state);
|
||
|
+ return BC_STS_ERR_USAGE;
|
||
|
+ }
|
||
|
+
|
||
|
+ frame = &idata->udata.u.DecOutData;
|
||
|
+
|
||
|
+ sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx, &frame->PibInfo, &dio);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ return (ctx->state & BC_LINK_SUSPEND) ? BC_STS_IO_USER_ABORT : sts;
|
||
|
+
|
||
|
+ frame->Flags = dio->uinfo.comp_flags;
|
||
|
+
|
||
|
+ if (frame->Flags & COMP_FLAG_FMT_CHANGE)
|
||
|
+ return bc_cproc_fmt_change(ctx, dio);
|
||
|
+
|
||
|
+ frame->OutPutBuffs.YuvBuff = dio->uinfo.xfr_buff;
|
||
|
+ frame->OutPutBuffs.YuvBuffSz = dio->uinfo.xfr_len;
|
||
|
+ frame->OutPutBuffs.UVbuffOffset = dio->uinfo.uv_offset;
|
||
|
+ frame->OutPutBuffs.b422Mode = dio->uinfo.b422mode;
|
||
|
+
|
||
|
+ frame->OutPutBuffs.YBuffDoneSz = dio->uinfo.y_done_sz;
|
||
|
+ frame->OutPutBuffs.UVBuffDoneSz = dio->uinfo.uv_done_sz;
|
||
|
+
|
||
|
+ crystalhd_unmap_dio(ctx->adp, dio);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_start_capture(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ ctx->state |= BC_LINK_CAP_EN;
|
||
|
+ if (ctx->state == BC_LINK_READY)
|
||
|
+ return crystalhd_hw_start_capture(&ctx->hw_ctx);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_flush_cap_buffs(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ crystalhd_dio_req *dio = NULL;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ BC_DEC_OUT_BUFF *frame;
|
||
|
+ uint32_t count;
|
||
|
+
|
||
|
+ if (!ctx || !idata) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!(ctx->state & BC_LINK_CAP_EN))
|
||
|
+ return BC_STS_ERR_USAGE;
|
||
|
+
|
||
|
+ /* We should ack flush even when we are in paused/suspend state */
|
||
|
+ if (!(ctx->state & BC_LINK_READY))
|
||
|
+ return crystalhd_hw_stop_capture(&ctx->hw_ctx);
|
||
|
+
|
||
|
+ ctx->state &= ~(BC_LINK_CAP_EN|BC_LINK_FMT_CHG);
|
||
|
+
|
||
|
+ frame = &idata->udata.u.DecOutData;
|
||
|
+ for (count = 0; count < BC_RX_LIST_CNT; count++) {
|
||
|
+
|
||
|
+ sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx, &frame->PibInfo, &dio);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ break;
|
||
|
+
|
||
|
+ crystalhd_unmap_dio(ctx->adp, dio);
|
||
|
+ }
|
||
|
+
|
||
|
+ return crystalhd_hw_stop_capture(&ctx->hw_ctx);
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_get_stats(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ BC_DTS_STATS *stats;
|
||
|
+ struct crystalhd_hw_stats hw_stats;
|
||
|
+
|
||
|
+ if (!ctx || !idata) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_hw_stats(&ctx->hw_ctx, &hw_stats);
|
||
|
+
|
||
|
+ stats = &idata->udata.u.drvStat;
|
||
|
+ stats->drvRLL = hw_stats.rdyq_count;
|
||
|
+ stats->drvFLL = hw_stats.freeq_count;
|
||
|
+ stats->DrvTotalFrmDropped = hw_stats.rx_errors;
|
||
|
+ stats->DrvTotalHWErrs = hw_stats.rx_errors + hw_stats.tx_errors;
|
||
|
+ stats->intCount = hw_stats.num_interrupts;
|
||
|
+ stats->DrvIgnIntrCnt = hw_stats.num_interrupts -
|
||
|
+ hw_stats.dev_interrupts;
|
||
|
+ stats->TxFifoBsyCnt = hw_stats.cin_busy;
|
||
|
+ stats->pauseCount = hw_stats.pause_cnt;
|
||
|
+
|
||
|
+ if (ctx->pwr_state_change)
|
||
|
+ stats->pwr_state_change = 1;
|
||
|
+ if (ctx->state & BC_LINK_PAUSED)
|
||
|
+ stats->DrvPauseTime = 1;
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_reset_stats(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ crystalhd_hw_stats(&ctx->hw_ctx, NULL);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS bc_cproc_chg_clk(struct crystalhd_cmd *ctx,
|
||
|
+ crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ BC_CLOCK *clock;
|
||
|
+ uint32_t oldClk;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (!ctx || !idata) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ clock = &idata->udata.u.clockValue;
|
||
|
+ oldClk = ctx->hw_ctx.core_clock_mhz;
|
||
|
+ ctx->hw_ctx.core_clock_mhz = clock->clk;
|
||
|
+
|
||
|
+ if (ctx->state & BC_LINK_READY) {
|
||
|
+ sts = crystalhd_hw_set_core_clock(&ctx->hw_ctx);
|
||
|
+ if (sts == BC_STS_CLK_NOCHG)
|
||
|
+ ctx->hw_ctx.core_clock_mhz = oldClk;
|
||
|
+ }
|
||
|
+
|
||
|
+ clock->clk = ctx->hw_ctx.core_clock_mhz;
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+/*=============== Cmd Proc Table.. ======================================*/
|
||
|
+static const crystalhd_cmd_tbl_t g_crystalhd_cproc_tbl[] = {
|
||
|
+ { BCM_IOC_GET_VERSION, bc_cproc_get_version, 0},
|
||
|
+ { BCM_IOC_GET_HWTYPE, bc_cproc_get_hwtype, 0},
|
||
|
+ { BCM_IOC_REG_RD, bc_cproc_reg_rd, 0},
|
||
|
+ { BCM_IOC_REG_WR, bc_cproc_reg_wr, 0},
|
||
|
+ { BCM_IOC_FPGA_RD, bc_cproc_link_reg_rd, 0},
|
||
|
+ { BCM_IOC_FPGA_WR, bc_cproc_link_reg_wr, 0},
|
||
|
+ { BCM_IOC_MEM_RD, bc_cproc_mem_rd, 0},
|
||
|
+ { BCM_IOC_MEM_WR, bc_cproc_mem_wr, 0},
|
||
|
+ { BCM_IOC_RD_PCI_CFG, bc_cproc_cfg_rd, 0},
|
||
|
+ { BCM_IOC_WR_PCI_CFG, bc_cproc_cfg_wr, 1},
|
||
|
+ { BCM_IOC_FW_DOWNLOAD, bc_cproc_download_fw, 1},
|
||
|
+ { BCM_IOC_FW_CMD, bc_cproc_do_fw_cmd, 1},
|
||
|
+ { BCM_IOC_PROC_INPUT, bc_cproc_proc_input, 1},
|
||
|
+ { BCM_IOC_ADD_RXBUFFS, bc_cproc_add_cap_buff, 1},
|
||
|
+ { BCM_IOC_FETCH_RXBUFF, bc_cproc_fetch_frame, 1},
|
||
|
+ { BCM_IOC_START_RX_CAP, bc_cproc_start_capture, 1},
|
||
|
+ { BCM_IOC_FLUSH_RX_CAP, bc_cproc_flush_cap_buffs, 1},
|
||
|
+ { BCM_IOC_GET_DRV_STAT, bc_cproc_get_stats, 0},
|
||
|
+ { BCM_IOC_RST_DRV_STAT, bc_cproc_reset_stats, 0},
|
||
|
+ { BCM_IOC_NOTIFY_MODE, bc_cproc_notify_mode, 0},
|
||
|
+ { BCM_IOC_CHG_CLK, bc_cproc_chg_clk, 0},
|
||
|
+ { BCM_IOC_END, NULL},
|
||
|
+};
|
||
|
+
|
||
|
+/*=============== Cmd Proc Functions.. ===================================*/
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_suspend - Power management suspend request.
|
||
|
+ * @ctx: Command layer context.
|
||
|
+ * @idata: Iodata - required for internal use.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * status
|
||
|
+ *
|
||
|
+ * 1. Set the state to Suspend.
|
||
|
+ * 2. Flush the Rx Buffers it will unmap all the buffers and
|
||
|
+ * stop the RxDMA engine.
|
||
|
+ * 3. Cancel The TX Io and Stop Dma Engine.
|
||
|
+ * 4. Put the DDR in to deep sleep.
|
||
|
+ * 5. Stop the hardware putting it in to Reset State.
|
||
|
+ *
|
||
|
+ * Current gstreamer frame work does not provide any power management
|
||
|
+ * related notification to user mode decoder plug-in. As a work-around
|
||
|
+ * we pass on the power mangement notification to our plug-in by completing
|
||
|
+ * all outstanding requests with BC_STS_IO_USER_ABORT return code.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_suspend(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
|
||
|
+{
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (!ctx || !idata) {
|
||
|
+ BCMLOG_ERR("Invalid Parameters\n");
|
||
|
+ return BC_STS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (ctx->state & BC_LINK_SUSPEND)
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (ctx->state == BC_LINK_INVALID) {
|
||
|
+ BCMLOG(BCMLOG_DBG, "Nothing To Do Suspend Success\n");
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+ }
|
||
|
+
|
||
|
+ ctx->state |= BC_LINK_SUSPEND;
|
||
|
+
|
||
|
+ bc_cproc_mark_pwr_state(ctx);
|
||
|
+
|
||
|
+ if (ctx->state & BC_LINK_CAP_EN) {
|
||
|
+ sts = bc_cproc_flush_cap_buffs(ctx, idata);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (ctx->tx_list_id) {
|
||
|
+ sts = crystalhd_hw_cancel_tx(&ctx->hw_ctx, ctx->tx_list_id);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_hw_suspend(&ctx->hw_ctx);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ return sts;
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DBG, "BCM70012 suspend success\n");
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_resume - Resume frame capture.
|
||
|
+ * @ctx: Command layer contextx.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * status
|
||
|
+ *
|
||
|
+ *
|
||
|
+ * Resume frame capture.
|
||
|
+ *
|
||
|
+ * PM_Resume can't resume the playback state back to pre-suspend state
|
||
|
+ * because we don't keep video clip related information within driver.
|
||
|
+ * To get back to the pre-suspend state App will re-open the device and
|
||
|
+ * start a new playback session from the pre-suspend clip position.
|
||
|
+ *
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_resume(struct crystalhd_cmd *ctx)
|
||
|
+{
|
||
|
+ BCMLOG(BCMLOG_DBG, "crystalhd_resume Success %x\n", ctx->state);
|
||
|
+
|
||
|
+ bc_cproc_mark_pwr_state(ctx);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_user_open - Create application handle.
|
||
|
+ * @ctx: Command layer contextx.
|
||
|
+ * @user_ctx: User ID context.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * status
|
||
|
+ *
|
||
|
+ * Creates an application specific UID and allocates
|
||
|
+ * application specific resources. HW layer initialization
|
||
|
+ * is done for the first open request.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_user_open(struct crystalhd_cmd *ctx,
|
||
|
+ struct crystalhd_user **user_ctx)
|
||
|
+{
|
||
|
+ struct crystalhd_user *uc;
|
||
|
+
|
||
|
+ if (!ctx || !user_ctx) {
|
||
|
+ BCMLOG_ERR("Invalid arg..\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ uc = bc_cproc_get_uid(ctx);
|
||
|
+ if (!uc) {
|
||
|
+ BCMLOG(BCMLOG_INFO, "No free user context...\n");
|
||
|
+ return BC_STS_BUSY;
|
||
|
+ }
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_INFO, "Opening new user[%x] handle\n", uc->uid);
|
||
|
+
|
||
|
+ crystalhd_hw_open(&ctx->hw_ctx, ctx->adp);
|
||
|
+
|
||
|
+ uc->in_use = 1;
|
||
|
+
|
||
|
+ *user_ctx = uc;
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_user_close - Close application handle.
|
||
|
+ * @ctx: Command layer contextx.
|
||
|
+ * @uc: User ID context.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * status
|
||
|
+ *
|
||
|
+ * Closer aplication handle and release app specific
|
||
|
+ * resources.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_user *uc)
|
||
|
+{
|
||
|
+ uint32_t mode = uc->mode;
|
||
|
+
|
||
|
+ ctx->user[uc->uid].mode = DTS_MODE_INV;
|
||
|
+ ctx->user[uc->uid].in_use = 0;
|
||
|
+ ctx->cin_wait_exit = 1;
|
||
|
+ ctx->pwr_state_change = 0;
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_INFO, "Closing user[%x] handle\n", uc->uid);
|
||
|
+
|
||
|
+ if ((mode == DTS_DIAG_MODE) || (mode == DTS_PLAYBACK_MODE)) {
|
||
|
+ crystalhd_hw_free_dma_rings(&ctx->hw_ctx);
|
||
|
+ crystalhd_destroy_dio_pool(ctx->adp);
|
||
|
+ } else if (bc_cproc_get_user_count(ctx)) {
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_hw_close(&ctx->hw_ctx);
|
||
|
+
|
||
|
+ ctx->state = BC_LINK_INVALID;
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_setup_cmd_context - Setup Command layer resources.
|
||
|
+ * @ctx: Command layer contextx.
|
||
|
+ * @adp: Adapter context
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * status
|
||
|
+ *
|
||
|
+ * Called at the time of driver load.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
|
||
|
+ struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ int i = 0;
|
||
|
+
|
||
|
+ if (!ctx || !adp) {
|
||
|
+ BCMLOG_ERR("Invalid arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (ctx->adp)
|
||
|
+ BCMLOG(BCMLOG_DBG, "Resetting Cmd context delete missing..\n");
|
||
|
+
|
||
|
+ ctx->adp = adp;
|
||
|
+ for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
|
||
|
+ ctx->user[i].uid = i;
|
||
|
+ ctx->user[i].in_use = 0;
|
||
|
+ ctx->user[i].mode = DTS_MODE_INV;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*Open and Close the Hardware to put it in to sleep state*/
|
||
|
+ crystalhd_hw_open(&ctx->hw_ctx, ctx->adp);
|
||
|
+ crystalhd_hw_close(&ctx->hw_ctx);
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_delete_cmd_context - Release Command layer resources.
|
||
|
+ * @ctx: Command layer contextx.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * status
|
||
|
+ *
|
||
|
+ * Called at the time of driver un-load.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx)
|
||
|
+{
|
||
|
+ BCMLOG(BCMLOG_DBG, "Deleting Command context..\n");
|
||
|
+
|
||
|
+ ctx->adp = NULL;
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_get_cmd_proc - Cproc table lookup.
|
||
|
+ * @ctx: Command layer contextx.
|
||
|
+ * @cmd: IOCTL command code.
|
||
|
+ * @uc: User ID context.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * command proc function pointer
|
||
|
+ *
|
||
|
+ * This function checks the process context, application's
|
||
|
+ * mode of operation and returns the function pointer
|
||
|
+ * from the cproc table.
|
||
|
+ */
|
||
|
+crystalhd_cmd_proc crystalhd_get_cmd_proc(struct crystalhd_cmd *ctx, uint32_t cmd,
|
||
|
+ struct crystalhd_user *uc)
|
||
|
+{
|
||
|
+ crystalhd_cmd_proc cproc = NULL;
|
||
|
+ unsigned int i, tbl_sz;
|
||
|
+
|
||
|
+ if (!ctx) {
|
||
|
+ BCMLOG_ERR("Invalid arg.. Cmd[%d]\n", cmd);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if ((cmd != BCM_IOC_GET_DRV_STAT) && (ctx->state & BC_LINK_SUSPEND)) {
|
||
|
+ BCMLOG_ERR("Invalid State [suspend Set].. Cmd[%d]\n", cmd);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ tbl_sz = sizeof(g_crystalhd_cproc_tbl) / sizeof(crystalhd_cmd_tbl_t);
|
||
|
+ for (i = 0; i < tbl_sz; i++) {
|
||
|
+ if (g_crystalhd_cproc_tbl[i].cmd_id == cmd) {
|
||
|
+ if ((uc->mode == DTS_MONITOR_MODE) &&
|
||
|
+ (g_crystalhd_cproc_tbl[i].block_mon)) {
|
||
|
+ BCMLOG(BCMLOG_INFO, "Blocking cmd %d \n", cmd);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ cproc = g_crystalhd_cproc_tbl[i].cmd_proc;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return cproc;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_cmd_interrupt - ISR entry point
|
||
|
+ * @ctx: Command layer contextx.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * TRUE: If interrupt from bcm70012 device.
|
||
|
+ *
|
||
|
+ *
|
||
|
+ * ISR entry point from OS layer.
|
||
|
+ */
|
||
|
+bool crystalhd_cmd_interrupt(struct crystalhd_cmd *ctx)
|
||
|
+{
|
||
|
+ if (!ctx) {
|
||
|
+ BCMLOG_ERR("Invalid arg..\n");
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ return crystalhd_hw_interrupt(ctx->adp, &ctx->hw_ctx);
|
||
|
+}
|
||
|
diff --git a/drivers/staging/crystalhd/crystalhd_cmds.h b/drivers/staging/crystalhd/crystalhd_cmds.h
|
||
|
new file mode 100644
|
||
|
index 0000000..6b290ae
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/crystalhd_cmds.h
|
||
|
@@ -0,0 +1,88 @@
|
||
|
+/***************************************************************************
|
||
|
+ * Copyright (c) 2005-2009, Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: crystalhd_cmds . h
|
||
|
+ *
|
||
|
+ * Description:
|
||
|
+ * BCM70010 Linux driver user command interfaces.
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ **********************************************************************
|
||
|
+ * This file is part of the crystalhd device driver.
|
||
|
+ *
|
||
|
+ * This driver is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, version 2 of the License.
|
||
|
+ *
|
||
|
+ * This driver is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this driver. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ **********************************************************************/
|
||
|
+
|
||
|
+#ifndef _CRYSTALHD_CMDS_H_
|
||
|
+#define _CRYSTALHD_CMDS_H_
|
||
|
+
|
||
|
+/*
|
||
|
+ * NOTE:: This is the main interface file between the Linux layer
|
||
|
+ * and the harware layer. This file will use the definitions
|
||
|
+ * from _dts_glob and dts_defs etc.. which are defined for
|
||
|
+ * windows.
|
||
|
+ */
|
||
|
+#include "crystalhd_misc.h"
|
||
|
+#include "crystalhd_hw.h"
|
||
|
+
|
||
|
+enum _crystalhd_state{
|
||
|
+ BC_LINK_INVALID = 0x00,
|
||
|
+ BC_LINK_INIT = 0x01,
|
||
|
+ BC_LINK_CAP_EN = 0x02,
|
||
|
+ BC_LINK_FMT_CHG = 0x04,
|
||
|
+ BC_LINK_SUSPEND = 0x10,
|
||
|
+ BC_LINK_PAUSED = 0x20,
|
||
|
+ BC_LINK_READY = (BC_LINK_INIT | BC_LINK_CAP_EN | BC_LINK_FMT_CHG),
|
||
|
+};
|
||
|
+
|
||
|
+struct crystalhd_user {
|
||
|
+ uint32_t uid;
|
||
|
+ uint32_t in_use;
|
||
|
+ uint32_t mode;
|
||
|
+};
|
||
|
+
|
||
|
+#define DTS_MODE_INV (-1)
|
||
|
+
|
||
|
+struct crystalhd_cmd {
|
||
|
+ uint32_t state;
|
||
|
+ struct crystalhd_adp *adp;
|
||
|
+ struct crystalhd_user user[BC_LINK_MAX_OPENS];
|
||
|
+
|
||
|
+ spinlock_t ctx_lock;
|
||
|
+ uint32_t tx_list_id;
|
||
|
+ uint32_t cin_wait_exit;
|
||
|
+ uint32_t pwr_state_change;
|
||
|
+ struct crystalhd_hw hw_ctx;
|
||
|
+};
|
||
|
+
|
||
|
+typedef BC_STATUS (*crystalhd_cmd_proc)(struct crystalhd_cmd *, crystalhd_ioctl_data *);
|
||
|
+
|
||
|
+typedef struct _crystalhd_cmd_tbl {
|
||
|
+ uint32_t cmd_id;
|
||
|
+ const crystalhd_cmd_proc cmd_proc;
|
||
|
+ uint32_t block_mon;
|
||
|
+} crystalhd_cmd_tbl_t;
|
||
|
+
|
||
|
+
|
||
|
+BC_STATUS crystalhd_suspend(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata);
|
||
|
+BC_STATUS crystalhd_resume(struct crystalhd_cmd *ctx);
|
||
|
+crystalhd_cmd_proc crystalhd_get_cmd_proc(struct crystalhd_cmd *ctx, uint32_t cmd,
|
||
|
+ struct crystalhd_user *uc);
|
||
|
+BC_STATUS crystalhd_user_open(struct crystalhd_cmd *ctx, struct crystalhd_user **user_ctx);
|
||
|
+BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_user *uc);
|
||
|
+BC_STATUS crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx, struct crystalhd_adp *adp);
|
||
|
+BC_STATUS crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx);
|
||
|
+bool crystalhd_cmd_interrupt(struct crystalhd_cmd *ctx);
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/staging/crystalhd/crystalhd_fw_if.h b/drivers/staging/crystalhd/crystalhd_fw_if.h
|
||
|
new file mode 100644
|
||
|
index 0000000..261cd19
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/crystalhd_fw_if.h
|
||
|
@@ -0,0 +1,369 @@
|
||
|
+/***************************************************************************
|
||
|
+ * Copyright (c) 2005-2009, Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: crystalhd_fw_if . h
|
||
|
+ *
|
||
|
+ * Description:
|
||
|
+ * BCM70012 Firmware interface definitions.
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ **********************************************************************
|
||
|
+ * This file is part of the crystalhd device driver.
|
||
|
+ *
|
||
|
+ * This driver is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, version 2 of the License.
|
||
|
+ *
|
||
|
+ * This driver is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this driver. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ **********************************************************************/
|
||
|
+
|
||
|
+#ifndef _CRYSTALHD_FW_IF_H_
|
||
|
+#define _CRYSTALHD_FW_IF_H_
|
||
|
+
|
||
|
+/* TBD: Pull in only required defs into this file.. */
|
||
|
+
|
||
|
+
|
||
|
+
|
||
|
+/* User Data Header */
|
||
|
+typedef struct user_data {
|
||
|
+ struct user_data *next;
|
||
|
+ uint32_t type;
|
||
|
+ uint32_t size;
|
||
|
+} UD_HDR;
|
||
|
+
|
||
|
+
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * MPEG Extension to the PPB *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+typedef struct {
|
||
|
+ uint32_t to_be_defined;
|
||
|
+ uint32_t valid;
|
||
|
+
|
||
|
+ /* Always valid, defaults to picture size if no
|
||
|
+ sequence display extension in the stream. */
|
||
|
+ uint32_t display_horizontal_size;
|
||
|
+ uint32_t display_vertical_size;
|
||
|
+
|
||
|
+ /* MPEG_VALID_PANSCAN
|
||
|
+ Offsets are a copy values from the MPEG stream. */
|
||
|
+ uint32_t offset_count;
|
||
|
+ int32_t horizontal_offset[3];
|
||
|
+ int32_t vertical_offset[3];
|
||
|
+
|
||
|
+ /* MPEG_VALID_USERDATA
|
||
|
+ User data is in the form of a linked list. */
|
||
|
+ int32_t userDataSize;
|
||
|
+ UD_HDR *userData;
|
||
|
+
|
||
|
+} PPB_MPEG;
|
||
|
+
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * VC1 Extension to the PPB *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+typedef struct {
|
||
|
+ uint32_t to_be_defined;
|
||
|
+ uint32_t valid;
|
||
|
+
|
||
|
+ /* Always valid, defaults to picture size if no
|
||
|
+ sequence display extension in the stream. */
|
||
|
+ uint32_t display_horizontal_size;
|
||
|
+ uint32_t display_vertical_size;
|
||
|
+
|
||
|
+ /* VC1 pan scan windows */
|
||
|
+ uint32_t num_panscan_windows;
|
||
|
+ int32_t ps_horiz_offset[4];
|
||
|
+ int32_t ps_vert_offset[4];
|
||
|
+ int32_t ps_width[4];
|
||
|
+ int32_t ps_height[4];
|
||
|
+
|
||
|
+ /* VC1_VALID_USERDATA
|
||
|
+ User data is in the form of a linked list. */
|
||
|
+ int32_t userDataSize;
|
||
|
+ UD_HDR *userData;
|
||
|
+
|
||
|
+} PPB_VC1;
|
||
|
+
|
||
|
+/*------------------------------------------------------*
|
||
|
+ * H.264 Extension to the PPB *
|
||
|
+ *------------------------------------------------------*/
|
||
|
+
|
||
|
+/**
|
||
|
+ * @brief Film grain SEI message.
|
||
|
+ *
|
||
|
+ * Content of the film grain SEI message.
|
||
|
+ */
|
||
|
+
|
||
|
+/* maximum number of model-values as for Thomson spec(standard says 5) */
|
||
|
+#define MAX_FGT_MODEL_VALUE (3)
|
||
|
+
|
||
|
+/* maximum number of intervals(as many as 256 intervals?) */
|
||
|
+#define MAX_FGT_VALUE_INTERVAL (256)
|
||
|
+
|
||
|
+typedef struct FGT_SEI {
|
||
|
+ struct FGT_SEI *next;
|
||
|
+ unsigned char model_values[3][MAX_FGT_VALUE_INTERVAL][MAX_FGT_MODEL_VALUE];
|
||
|
+ unsigned char upper_bound[3][MAX_FGT_VALUE_INTERVAL];
|
||
|
+ unsigned char lower_bound[3][MAX_FGT_VALUE_INTERVAL];
|
||
|
+
|
||
|
+ unsigned char cancel_flag; /* Cancel flag: 1 no film grain. */
|
||
|
+ unsigned char model_id; /* Model id. */
|
||
|
+
|
||
|
+ /* +unused SE based on Thomson spec */
|
||
|
+ unsigned char color_desc_flag; /* Separate color descrition flag. */
|
||
|
+ unsigned char bit_depth_luma; /* Bit depth luma minus 8. */
|
||
|
+ unsigned char bit_depth_chroma; /* Bit depth chroma minus 8. */
|
||
|
+ unsigned char full_range_flag; /* Full range flag. */
|
||
|
+ unsigned char color_primaries; /* Color primaries. */
|
||
|
+ unsigned char transfer_charact; /* Transfer characteristics. */
|
||
|
+ unsigned char matrix_coeff; /*< Matrix coefficients. */
|
||
|
+ /* -unused SE based on Thomson spec */
|
||
|
+
|
||
|
+ unsigned char blending_mode_id; /* Blending mode. */
|
||
|
+ unsigned char log2_scale_factor; /* Log2 scale factor (2-7). */
|
||
|
+ unsigned char comp_flag[3]; /* Components [0,2] parameters present flag. */
|
||
|
+ unsigned char num_intervals_minus1[3]; /* Number of intensity level intervals. */
|
||
|
+ unsigned char num_model_values[3]; /* Number of model values. */
|
||
|
+ uint16_t repetition_period; /* Repetition period (0-16384) */
|
||
|
+
|
||
|
+} FGT_SEI;
|
||
|
+
|
||
|
+typedef struct {
|
||
|
+ /* 'valid' specifies which fields (or sets of
|
||
|
+ * fields) below are valid. If the corresponding
|
||
|
+ * bit in 'valid' is NOT set then that field(s)
|
||
|
+ * is (are) not initialized. */
|
||
|
+ uint32_t valid;
|
||
|
+
|
||
|
+ int32_t poc_top; /* POC for Top Field/Frame */
|
||
|
+ int32_t poc_bottom; /* POC for Bottom Field */
|
||
|
+ uint32_t idr_pic_id;
|
||
|
+
|
||
|
+ /* H264_VALID_PANSCAN */
|
||
|
+ uint32_t pan_scan_count;
|
||
|
+ int32_t pan_scan_left[3];
|
||
|
+ int32_t pan_scan_right[3];
|
||
|
+ int32_t pan_scan_top[3];
|
||
|
+ int32_t pan_scan_bottom[3];
|
||
|
+
|
||
|
+ /* H264_VALID_CT_TYPE */
|
||
|
+ uint32_t ct_type_count;
|
||
|
+ uint32_t ct_type[3];
|
||
|
+
|
||
|
+ /* H264_VALID_SPS_CROP */
|
||
|
+ int32_t sps_crop_left;
|
||
|
+ int32_t sps_crop_right;
|
||
|
+ int32_t sps_crop_top;
|
||
|
+ int32_t sps_crop_bottom;
|
||
|
+
|
||
|
+ /* H264_VALID_VUI */
|
||
|
+ uint32_t chroma_top;
|
||
|
+ uint32_t chroma_bottom;
|
||
|
+
|
||
|
+ /* H264_VALID_USER */
|
||
|
+ uint32_t user_data_size;
|
||
|
+ UD_HDR *user_data;
|
||
|
+
|
||
|
+ /* H264 VALID FGT */
|
||
|
+ FGT_SEI *pfgt;
|
||
|
+
|
||
|
+} PPB_H264;
|
||
|
+
|
||
|
+typedef struct {
|
||
|
+ /* Common fields. */
|
||
|
+ uint32_t picture_number; /* Ordinal display number */
|
||
|
+ uint32_t video_buffer; /* Video (picbuf) number */
|
||
|
+ uint32_t video_address; /* Address of picbuf Y */
|
||
|
+ uint32_t video_address_uv; /* Address of picbuf UV */
|
||
|
+ uint32_t video_stripe; /* Picbuf stripe */
|
||
|
+ uint32_t video_width; /* Picbuf width */
|
||
|
+ uint32_t video_height; /* Picbuf height */
|
||
|
+
|
||
|
+ uint32_t channel_id; /* Decoder channel ID */
|
||
|
+ uint32_t status; /* reserved */
|
||
|
+ uint32_t width; /* pixels */
|
||
|
+ uint32_t height; /* pixels */
|
||
|
+ uint32_t chroma_format; /* see above */
|
||
|
+ uint32_t pulldown; /* see above */
|
||
|
+ uint32_t flags; /* see above */
|
||
|
+ uint32_t pts; /* 32 LSBs of PTS */
|
||
|
+ uint32_t protocol; /* protocolXXX (above) */
|
||
|
+
|
||
|
+ uint32_t frame_rate; /* see above */
|
||
|
+ uint32_t matrix_coeff; /* see above */
|
||
|
+ uint32_t aspect_ratio; /* see above */
|
||
|
+ uint32_t colour_primaries; /* see above */
|
||
|
+ uint32_t transfer_char; /* see above */
|
||
|
+ uint32_t pcr_offset; /* 45kHz if PCR type; else 27MHz */
|
||
|
+ uint32_t n_drop; /* Number of pictures to be dropped */
|
||
|
+
|
||
|
+ uint32_t custom_aspect_ratio_width_height;
|
||
|
+ /* upper 16-bits is Y and lower 16-bits is X */
|
||
|
+
|
||
|
+ uint32_t picture_tag; /* Indexing tag from BUD packets */
|
||
|
+ uint32_t picture_done_payload;
|
||
|
+ uint32_t picture_meta_payload;
|
||
|
+ uint32_t reserved[1];
|
||
|
+
|
||
|
+ /* Protocol-specific extensions. */
|
||
|
+ union {
|
||
|
+ PPB_H264 h264;
|
||
|
+ PPB_MPEG mpeg;
|
||
|
+ PPB_VC1 vc1;
|
||
|
+ } other;
|
||
|
+
|
||
|
+} PPB;
|
||
|
+
|
||
|
+typedef struct {
|
||
|
+ uint32_t bFormatChange;
|
||
|
+ uint32_t resolution;
|
||
|
+ uint32_t channelId;
|
||
|
+ uint32_t ppbPtr;
|
||
|
+ int32_t ptsStcOffset;
|
||
|
+ uint32_t zeroPanscanValid;
|
||
|
+ uint32_t dramOutBufAddr;
|
||
|
+ uint32_t yComponent;
|
||
|
+ PPB ppb;
|
||
|
+
|
||
|
+} C011_PIB;
|
||
|
+
|
||
|
+
|
||
|
+
|
||
|
+typedef struct {
|
||
|
+ uint32_t command;
|
||
|
+ uint32_t sequence;
|
||
|
+ uint32_t status;
|
||
|
+ uint32_t picBuf;
|
||
|
+ uint32_t picRelBuf;
|
||
|
+ uint32_t picInfoDeliveryQ;
|
||
|
+ uint32_t picInfoReleaseQ;
|
||
|
+ uint32_t channelStatus;
|
||
|
+ uint32_t userDataDeliveryQ;
|
||
|
+ uint32_t userDataReleaseQ;
|
||
|
+ uint32_t transportStreamCaptureAddr;
|
||
|
+ uint32_t asyncEventQ;
|
||
|
+
|
||
|
+} DecRspChannelStartVideo;
|
||
|
+
|
||
|
+#define eCMD_C011_CMD_BASE (0x73763000)
|
||
|
+
|
||
|
+/* host commands */
|
||
|
+typedef enum {
|
||
|
+ eCMD_TS_GET_NEXT_PIC = 0x7376F100, /* debug get next picture */
|
||
|
+ eCMD_TS_GET_LAST_PIC = 0x7376F102, /* debug get last pic status */
|
||
|
+ eCMD_TS_READ_WRITE_MEM = 0x7376F104, /* debug read write memory */
|
||
|
+
|
||
|
+ /* New API commands */
|
||
|
+ /* General commands */
|
||
|
+ eCMD_C011_INIT = eCMD_C011_CMD_BASE + 0x01,
|
||
|
+ eCMD_C011_RESET = eCMD_C011_CMD_BASE + 0x02,
|
||
|
+ eCMD_C011_SELF_TEST = eCMD_C011_CMD_BASE + 0x03,
|
||
|
+ eCMD_C011_GET_VERSION = eCMD_C011_CMD_BASE + 0x04,
|
||
|
+ eCMD_C011_GPIO = eCMD_C011_CMD_BASE + 0x05,
|
||
|
+ eCMD_C011_DEBUG_SETUP = eCMD_C011_CMD_BASE + 0x06,
|
||
|
+
|
||
|
+ /* Decoding commands */
|
||
|
+ eCMD_C011_DEC_CHAN_OPEN = eCMD_C011_CMD_BASE + 0x100,
|
||
|
+ eCMD_C011_DEC_CHAN_CLOSE = eCMD_C011_CMD_BASE + 0x101,
|
||
|
+ eCMD_C011_DEC_CHAN_ACTIVATE = eCMD_C011_CMD_BASE + 0x102,
|
||
|
+ eCMD_C011_DEC_CHAN_STATUS = eCMD_C011_CMD_BASE + 0x103,
|
||
|
+ eCMD_C011_DEC_CHAN_FLUSH = eCMD_C011_CMD_BASE + 0x104,
|
||
|
+ eCMD_C011_DEC_CHAN_TRICK_PLAY = eCMD_C011_CMD_BASE + 0x105,
|
||
|
+ eCMD_C011_DEC_CHAN_TS_PIDS = eCMD_C011_CMD_BASE + 0x106,
|
||
|
+ eCMD_C011_DEC_CHAN_PS_STREAM_ID = eCMD_C011_CMD_BASE + 0x107,
|
||
|
+ eCMD_C011_DEC_CHAN_INPUT_PARAMS = eCMD_C011_CMD_BASE + 0x108,
|
||
|
+ eCMD_C011_DEC_CHAN_VIDEO_OUTPUT = eCMD_C011_CMD_BASE + 0x109,
|
||
|
+ eCMD_C011_DEC_CHAN_OUTPUT_FORMAT = eCMD_C011_CMD_BASE + 0x10A,
|
||
|
+ eCMD_C011_DEC_CHAN_SCALING_FILTERS = eCMD_C011_CMD_BASE + 0x10B,
|
||
|
+ eCMD_C011_DEC_CHAN_OSD_MODE = eCMD_C011_CMD_BASE + 0x10D,
|
||
|
+ eCMD_C011_DEC_CHAN_DROP = eCMD_C011_CMD_BASE + 0x10E,
|
||
|
+ eCMD_C011_DEC_CHAN_RELEASE = eCMD_C011_CMD_BASE + 0x10F,
|
||
|
+ eCMD_C011_DEC_CHAN_STREAM_SETTINGS = eCMD_C011_CMD_BASE + 0x110,
|
||
|
+ eCMD_C011_DEC_CHAN_PAUSE_OUTPUT = eCMD_C011_CMD_BASE + 0x111,
|
||
|
+ eCMD_C011_DEC_CHAN_CHANGE = eCMD_C011_CMD_BASE + 0x112,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_STC = eCMD_C011_CMD_BASE + 0x113,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_PTS = eCMD_C011_CMD_BASE + 0x114,
|
||
|
+ eCMD_C011_DEC_CHAN_CC_MODE = eCMD_C011_CMD_BASE + 0x115,
|
||
|
+ eCMD_C011_DEC_CREATE_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x116,
|
||
|
+ eCMD_C011_DEC_COPY_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x117,
|
||
|
+ eCMD_C011_DEC_DELETE_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x118,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_DECYPTION = eCMD_C011_CMD_BASE + 0x119,
|
||
|
+ eCMD_C011_DEC_CHAN_START_VIDEO = eCMD_C011_CMD_BASE + 0x11A,
|
||
|
+ eCMD_C011_DEC_CHAN_STOP_VIDEO = eCMD_C011_CMD_BASE + 0x11B,
|
||
|
+ eCMD_C011_DEC_CHAN_PIC_CAPTURE = eCMD_C011_CMD_BASE + 0x11C,
|
||
|
+ eCMD_C011_DEC_CHAN_PAUSE = eCMD_C011_CMD_BASE + 0x11D,
|
||
|
+ eCMD_C011_DEC_CHAN_PAUSE_STATE = eCMD_C011_CMD_BASE + 0x11E,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_SLOWM_RATE = eCMD_C011_CMD_BASE + 0x11F,
|
||
|
+ eCMD_C011_DEC_CHAN_GET_SLOWM_RATE = eCMD_C011_CMD_BASE + 0x120,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_FF_RATE = eCMD_C011_CMD_BASE + 0x121,
|
||
|
+ eCMD_C011_DEC_CHAN_GET_FF_RATE = eCMD_C011_CMD_BASE + 0x122,
|
||
|
+ eCMD_C011_DEC_CHAN_FRAME_ADVANCE = eCMD_C011_CMD_BASE + 0x123,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_SKIP_PIC_MODE = eCMD_C011_CMD_BASE + 0x124,
|
||
|
+ eCMD_C011_DEC_CHAN_GET_SKIP_PIC_MODE = eCMD_C011_CMD_BASE + 0x125,
|
||
|
+ eCMD_C011_DEC_CHAN_FILL_PIC_BUF = eCMD_C011_CMD_BASE + 0x126,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_CONTINUITY_CHECK = eCMD_C011_CMD_BASE + 0x127,
|
||
|
+ eCMD_C011_DEC_CHAN_GET_CONTINUITY_CHECK = eCMD_C011_CMD_BASE + 0x128,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_BRCM_TRICK_MODE = eCMD_C011_CMD_BASE + 0x129,
|
||
|
+ eCMD_C011_DEC_CHAN_GET_BRCM_TRICK_MODE = eCMD_C011_CMD_BASE + 0x12A,
|
||
|
+ eCMD_C011_DEC_CHAN_REVERSE_FIELD_STATUS = eCMD_C011_CMD_BASE + 0x12B,
|
||
|
+ eCMD_C011_DEC_CHAN_I_PICTURE_FOUND = eCMD_C011_CMD_BASE + 0x12C,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_PARAMETER = eCMD_C011_CMD_BASE + 0x12D,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_USER_DATA_MODE = eCMD_C011_CMD_BASE + 0x12E,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_PAUSE_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x12F,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_SLOW_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x130,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_FF_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x131,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_DISPLAY_TIMING_MODE = eCMD_C011_CMD_BASE + 0x132,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x133,
|
||
|
+ eCMD_C011_DEC_CHAN_GET_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x134,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_REVERSE_FIELD = eCMD_C011_CMD_BASE + 0x135,
|
||
|
+ eCMD_C011_DEC_CHAN_STREAM_OPEN = eCMD_C011_CMD_BASE + 0x136,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_PCR_PID = eCMD_C011_CMD_BASE + 0x137,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_VID_PID = eCMD_C011_CMD_BASE + 0x138,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_PAN_SCAN_MODE = eCMD_C011_CMD_BASE + 0x139,
|
||
|
+ eCMD_C011_DEC_CHAN_START_DISPLAY_AT_PTS = eCMD_C011_CMD_BASE + 0x140,
|
||
|
+ eCMD_C011_DEC_CHAN_STOP_DISPLAY_AT_PTS = eCMD_C011_CMD_BASE + 0x141,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_DISPLAY_ORDER = eCMD_C011_CMD_BASE + 0x142,
|
||
|
+ eCMD_C011_DEC_CHAN_GET_DISPLAY_ORDER = eCMD_C011_CMD_BASE + 0x143,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_HOST_TRICK_MODE = eCMD_C011_CMD_BASE + 0x144,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_OPERATION_MODE = eCMD_C011_CMD_BASE + 0x145,
|
||
|
+ eCMD_C011_DEC_CHAN_DISPLAY_PAUSE_UNTO_PTS = eCMD_C011_CMD_BASE + 0x146,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_PTS_STC_DIFF_THRESHOLD = eCMD_C011_CMD_BASE + 0x147,
|
||
|
+ eCMD_C011_DEC_CHAN_SEND_COMPRESSED_BUF = eCMD_C011_CMD_BASE + 0x148,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_CLIPPING = eCMD_C011_CMD_BASE + 0x149,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_PARAMETERS_FOR_HARD_RESET_INTERRUPT_TO_HOST
|
||
|
+ = eCMD_C011_CMD_BASE + 0x150,
|
||
|
+
|
||
|
+ /* Decoder RevD commands */
|
||
|
+ eCMD_C011_DEC_CHAN_SET_CSC = eCMD_C011_CMD_BASE + 0x180, /* color space conversion */
|
||
|
+ eCMD_C011_DEC_CHAN_SET_RANGE_REMAP = eCMD_C011_CMD_BASE + 0x181,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_FGT = eCMD_C011_CMD_BASE + 0x182,
|
||
|
+ /* Note: 0x183 not implemented yet in Rev D main */
|
||
|
+ eCMD_C011_DEC_CHAN_SET_LASTPICTURE_PADDING = eCMD_C011_CMD_BASE + 0x183,
|
||
|
+
|
||
|
+ /* Decoder 7412 commands (7412-only) */
|
||
|
+ eCMD_C011_DEC_CHAN_SET_CONTENT_KEY = eCMD_C011_CMD_BASE + 0x190,
|
||
|
+ eCMD_C011_DEC_CHAN_SET_SESSION_KEY = eCMD_C011_CMD_BASE + 0x191,
|
||
|
+ eCMD_C011_DEC_CHAN_FMT_CHANGE_ACK = eCMD_C011_CMD_BASE + 0x192,
|
||
|
+
|
||
|
+ eCMD_C011_DEC_CHAN_CUSTOM_VIDOUT = eCMD_C011_CMD_BASE + 0x1FF,
|
||
|
+
|
||
|
+ /* Encoding commands */
|
||
|
+ eCMD_C011_ENC_CHAN_OPEN = eCMD_C011_CMD_BASE + 0x200,
|
||
|
+ eCMD_C011_ENC_CHAN_CLOSE = eCMD_C011_CMD_BASE + 0x201,
|
||
|
+ eCMD_C011_ENC_CHAN_ACTIVATE = eCMD_C011_CMD_BASE + 0x202,
|
||
|
+ eCMD_C011_ENC_CHAN_CONTROL = eCMD_C011_CMD_BASE + 0x203,
|
||
|
+ eCMD_C011_ENC_CHAN_STATISTICS = eCMD_C011_CMD_BASE + 0x204,
|
||
|
+
|
||
|
+ eNOTIFY_C011_ENC_CHAN_EVENT = eCMD_C011_CMD_BASE + 0x210,
|
||
|
+
|
||
|
+} eC011_TS_CMD;
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/staging/crystalhd/crystalhd_hw.c b/drivers/staging/crystalhd/crystalhd_hw.c
|
||
|
new file mode 100644
|
||
|
index 0000000..01819d3
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/crystalhd_hw.c
|
||
|
@@ -0,0 +1,2395 @@
|
||
|
+/***************************************************************************
|
||
|
+ * Copyright (c) 2005-2009, Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: crystalhd_hw . c
|
||
|
+ *
|
||
|
+ * Description:
|
||
|
+ * BCM70010 Linux driver HW layer.
|
||
|
+ *
|
||
|
+ **********************************************************************
|
||
|
+ * This file is part of the crystalhd device driver.
|
||
|
+ *
|
||
|
+ * This driver is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, version 2 of the License.
|
||
|
+ *
|
||
|
+ * This driver is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this driver. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ **********************************************************************/
|
||
|
+
|
||
|
+#include <linux/pci.h>
|
||
|
+#include <linux/delay.h>
|
||
|
+#include "crystalhd_hw.h"
|
||
|
+
|
||
|
+/* Functions internal to this file */
|
||
|
+
|
||
|
+static void crystalhd_enable_uarts(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ bc_dec_reg_wr(adp, UartSelectA, BSVS_UART_STREAM);
|
||
|
+ bc_dec_reg_wr(adp, UartSelectB, BSVS_UART_DEC_OUTER);
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static void crystalhd_start_dram(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ bc_dec_reg_wr(adp, SDRAM_PARAM, ((40 / 5 - 1) << 0) |
|
||
|
+ /* tras (40ns tras)/(5ns period) -1 ((15/5 - 1) << 4) | // trcd */
|
||
|
+ ((15 / 5 - 1) << 7) | /* trp */
|
||
|
+ ((10 / 5 - 1) << 10) | /* trrd */
|
||
|
+ ((15 / 5 + 1) << 12) | /* twr */
|
||
|
+ ((2 + 1) << 16) | /* twtr */
|
||
|
+ ((70 / 5 - 2) << 19) | /* trfc */
|
||
|
+ (0 << 23));
|
||
|
+
|
||
|
+ bc_dec_reg_wr(adp, SDRAM_PRECHARGE, 0);
|
||
|
+ bc_dec_reg_wr(adp, SDRAM_EXT_MODE, 2);
|
||
|
+ bc_dec_reg_wr(adp, SDRAM_MODE, 0x132);
|
||
|
+ bc_dec_reg_wr(adp, SDRAM_PRECHARGE, 0);
|
||
|
+ bc_dec_reg_wr(adp, SDRAM_REFRESH, 0);
|
||
|
+ bc_dec_reg_wr(adp, SDRAM_REFRESH, 0);
|
||
|
+ bc_dec_reg_wr(adp, SDRAM_MODE, 0x32);
|
||
|
+ /* setting the refresh rate here */
|
||
|
+ bc_dec_reg_wr(adp, SDRAM_REF_PARAM, ((1 << 12) | 96));
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static bool crystalhd_bring_out_of_rst(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ link_misc_perst_deco_ctrl rst_deco_cntrl;
|
||
|
+ link_misc_perst_clk_ctrl rst_clk_cntrl;
|
||
|
+ uint32_t temp;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Link clocks: MISC_PERST_CLOCK_CTRL Clear PLL power down bit,
|
||
|
+ * delay to allow PLL to lock Clear alternate clock, stop clock bits
|
||
|
+ */
|
||
|
+ rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
|
||
|
+ rst_clk_cntrl.pll_pwr_dn = 0;
|
||
|
+ crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
|
||
|
+ msleep_interruptible(50);
|
||
|
+
|
||
|
+ rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
|
||
|
+ rst_clk_cntrl.stop_core_clk = 0;
|
||
|
+ rst_clk_cntrl.sel_alt_clk = 0;
|
||
|
+
|
||
|
+ crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
|
||
|
+ msleep_interruptible(50);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Bus Arbiter Timeout: GISB_ARBITER_TIMER
|
||
|
+ * Set internal bus arbiter timeout to 40us based on core clock speed
|
||
|
+ * (63MHz * 40us = 0x9D8)
|
||
|
+ */
|
||
|
+ crystalhd_reg_wr(adp, GISB_ARBITER_TIMER, 0x9D8);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Decoder clocks: MISC_PERST_DECODER_CTRL
|
||
|
+ * Enable clocks while 7412 reset is asserted, delay
|
||
|
+ * De-assert 7412 reset
|
||
|
+ */
|
||
|
+ rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_DECODER_CTRL);
|
||
|
+ rst_deco_cntrl.stop_bcm_7412_clk = 0;
|
||
|
+ rst_deco_cntrl.bcm7412_rst = 1;
|
||
|
+ crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL, rst_deco_cntrl.whole_reg);
|
||
|
+ msleep_interruptible(10);
|
||
|
+
|
||
|
+ rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_DECODER_CTRL);
|
||
|
+ rst_deco_cntrl.bcm7412_rst = 0;
|
||
|
+ crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL, rst_deco_cntrl.whole_reg);
|
||
|
+ msleep_interruptible(50);
|
||
|
+
|
||
|
+ /* Disable OTP_CONTENT_MISC to 0 to disable all secure modes */
|
||
|
+ crystalhd_reg_wr(adp, OTP_CONTENT_MISC, 0);
|
||
|
+
|
||
|
+ /* Clear bit 29 of 0x404 */
|
||
|
+ temp = crystalhd_reg_rd(adp, PCIE_TL_TRANSACTION_CONFIGURATION);
|
||
|
+ temp &= ~BC_BIT(29);
|
||
|
+ crystalhd_reg_wr(adp, PCIE_TL_TRANSACTION_CONFIGURATION, temp);
|
||
|
+
|
||
|
+ /* 2.5V regulator must be set to 2.6 volts (+6%) */
|
||
|
+ /* FIXME: jarod: what's the point of this reg read? */
|
||
|
+ temp = crystalhd_reg_rd(adp, MISC_PERST_VREG_CTRL);
|
||
|
+ crystalhd_reg_wr(adp, MISC_PERST_VREG_CTRL, 0xF3);
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static bool crystalhd_put_in_reset(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ link_misc_perst_deco_ctrl rst_deco_cntrl;
|
||
|
+ link_misc_perst_clk_ctrl rst_clk_cntrl;
|
||
|
+ uint32_t temp;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Decoder clocks: MISC_PERST_DECODER_CTRL
|
||
|
+ * Assert 7412 reset, delay
|
||
|
+ * Assert 7412 stop clock
|
||
|
+ */
|
||
|
+ rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_DECODER_CTRL);
|
||
|
+ rst_deco_cntrl.stop_bcm_7412_clk = 1;
|
||
|
+ crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL, rst_deco_cntrl.whole_reg);
|
||
|
+ msleep_interruptible(50);
|
||
|
+
|
||
|
+ /* Bus Arbiter Timeout: GISB_ARBITER_TIMER
|
||
|
+ * Set internal bus arbiter timeout to 40us based on core clock speed
|
||
|
+ * (6.75MHZ * 40us = 0x10E)
|
||
|
+ */
|
||
|
+ crystalhd_reg_wr(adp, GISB_ARBITER_TIMER, 0x10E);
|
||
|
+
|
||
|
+ /* Link clocks: MISC_PERST_CLOCK_CTRL
|
||
|
+ * Stop core clk, delay
|
||
|
+ * Set alternate clk, delay, set PLL power down
|
||
|
+ */
|
||
|
+ rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
|
||
|
+ rst_clk_cntrl.stop_core_clk = 1;
|
||
|
+ rst_clk_cntrl.sel_alt_clk = 1;
|
||
|
+ crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
|
||
|
+ msleep_interruptible(50);
|
||
|
+
|
||
|
+ rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
|
||
|
+ rst_clk_cntrl.pll_pwr_dn = 1;
|
||
|
+ crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Read and restore the Transaction Configuration Register
|
||
|
+ * after core reset
|
||
|
+ */
|
||
|
+ temp = crystalhd_reg_rd(adp, PCIE_TL_TRANSACTION_CONFIGURATION);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Link core soft reset: MISC3_RESET_CTRL
|
||
|
+ * - Write BIT[0]=1 and read it back for core reset to take place
|
||
|
+ */
|
||
|
+ crystalhd_reg_wr(adp, MISC3_RESET_CTRL, 1);
|
||
|
+ rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC3_RESET_CTRL);
|
||
|
+ msleep_interruptible(50);
|
||
|
+
|
||
|
+ /* restore the transaction configuration register */
|
||
|
+ crystalhd_reg_wr(adp, PCIE_TL_TRANSACTION_CONFIGURATION, temp);
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_disable_interrupts(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ intr_mask_reg intr_mask;
|
||
|
+ intr_mask.whole_reg = crystalhd_reg_rd(adp, INTR_INTR_MSK_STS_REG);
|
||
|
+ intr_mask.mask_pcie_err = 1;
|
||
|
+ intr_mask.mask_pcie_rbusmast_err = 1;
|
||
|
+ intr_mask.mask_pcie_rgr_bridge = 1;
|
||
|
+ intr_mask.mask_rx_done = 1;
|
||
|
+ intr_mask.mask_rx_err = 1;
|
||
|
+ intr_mask.mask_tx_done = 1;
|
||
|
+ intr_mask.mask_tx_err = 1;
|
||
|
+ crystalhd_reg_wr(adp, INTR_INTR_MSK_SET_REG, intr_mask.whole_reg);
|
||
|
+
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_enable_interrupts(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ intr_mask_reg intr_mask;
|
||
|
+ intr_mask.whole_reg = crystalhd_reg_rd(adp, INTR_INTR_MSK_STS_REG);
|
||
|
+ intr_mask.mask_pcie_err = 1;
|
||
|
+ intr_mask.mask_pcie_rbusmast_err = 1;
|
||
|
+ intr_mask.mask_pcie_rgr_bridge = 1;
|
||
|
+ intr_mask.mask_rx_done = 1;
|
||
|
+ intr_mask.mask_rx_err = 1;
|
||
|
+ intr_mask.mask_tx_done = 1;
|
||
|
+ intr_mask.mask_tx_err = 1;
|
||
|
+ crystalhd_reg_wr(adp, INTR_INTR_MSK_CLR_REG, intr_mask.whole_reg);
|
||
|
+
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_clear_errors(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ uint32_t reg;
|
||
|
+
|
||
|
+ /* FIXME: jarod: wouldn't we want to write a 0 to the reg? Or does the write clear the bits specified? */
|
||
|
+ reg = crystalhd_reg_rd(adp, MISC1_Y_RX_ERROR_STATUS);
|
||
|
+ if (reg)
|
||
|
+ crystalhd_reg_wr(adp, MISC1_Y_RX_ERROR_STATUS, reg);
|
||
|
+
|
||
|
+ reg = crystalhd_reg_rd(adp, MISC1_UV_RX_ERROR_STATUS);
|
||
|
+ if (reg)
|
||
|
+ crystalhd_reg_wr(adp, MISC1_UV_RX_ERROR_STATUS, reg);
|
||
|
+
|
||
|
+ reg = crystalhd_reg_rd(adp, MISC1_TX_DMA_ERROR_STATUS);
|
||
|
+ if (reg)
|
||
|
+ crystalhd_reg_wr(adp, MISC1_TX_DMA_ERROR_STATUS, reg);
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_clear_interrupts(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ uint32_t intr_sts = crystalhd_reg_rd(adp, INTR_INTR_STATUS);
|
||
|
+
|
||
|
+ if (intr_sts) {
|
||
|
+ crystalhd_reg_wr(adp, INTR_INTR_CLR_REG, intr_sts);
|
||
|
+
|
||
|
+ /* Write End Of Interrupt for PCIE */
|
||
|
+ crystalhd_reg_wr(adp, INTR_EOI_CTRL, 1);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_soft_rst(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ uint32_t val;
|
||
|
+
|
||
|
+ /* Assert c011 soft reset*/
|
||
|
+ bc_dec_reg_wr(adp, DecHt_HostSwReset, 0x00000001);
|
||
|
+ msleep_interruptible(50);
|
||
|
+
|
||
|
+ /* Release c011 soft reset*/
|
||
|
+ bc_dec_reg_wr(adp, DecHt_HostSwReset, 0x00000000);
|
||
|
+
|
||
|
+ /* Disable Stuffing..*/
|
||
|
+ val = crystalhd_reg_rd(adp, MISC2_GLOBAL_CTRL);
|
||
|
+ val |= BC_BIT(8);
|
||
|
+ crystalhd_reg_wr(adp, MISC2_GLOBAL_CTRL, val);
|
||
|
+}
|
||
|
+
|
||
|
+static bool crystalhd_load_firmware_config(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ uint32_t i = 0, reg;
|
||
|
+
|
||
|
+ crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (BC_DRAM_FW_CFG_ADDR >> 19));
|
||
|
+
|
||
|
+ crystalhd_reg_wr(adp, AES_CMD, 0);
|
||
|
+ crystalhd_reg_wr(adp, AES_CONFIG_INFO, (BC_DRAM_FW_CFG_ADDR & 0x7FFFF));
|
||
|
+ crystalhd_reg_wr(adp, AES_CMD, 0x1);
|
||
|
+
|
||
|
+ /* FIXME: jarod: I've seen this fail, and introducing extra delays helps... */
|
||
|
+ for (i = 0; i < 100; ++i) {
|
||
|
+ reg = crystalhd_reg_rd(adp, AES_STATUS);
|
||
|
+ if (reg & 0x1)
|
||
|
+ return true;
|
||
|
+ msleep_interruptible(10);
|
||
|
+ }
|
||
|
+
|
||
|
+ return false;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static bool crystalhd_start_device(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ uint32_t dbg_options, glb_cntrl = 0, reg_pwrmgmt = 0;
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_INFO, "Starting BCM70012 Device\n");
|
||
|
+
|
||
|
+ reg_pwrmgmt = crystalhd_reg_rd(adp, PCIE_DLL_DATA_LINK_CONTROL);
|
||
|
+ reg_pwrmgmt &= ~ASPM_L1_ENABLE;
|
||
|
+
|
||
|
+ crystalhd_reg_wr(adp, PCIE_DLL_DATA_LINK_CONTROL, reg_pwrmgmt);
|
||
|
+
|
||
|
+ if (!crystalhd_bring_out_of_rst(adp)) {
|
||
|
+ BCMLOG_ERR("Failed To Bring Link Out Of Reset\n");
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_disable_interrupts(adp);
|
||
|
+
|
||
|
+ crystalhd_clear_errors(adp);
|
||
|
+
|
||
|
+ crystalhd_clear_interrupts(adp);
|
||
|
+
|
||
|
+ crystalhd_enable_interrupts(adp);
|
||
|
+
|
||
|
+ /* Enable the option for getting the total no. of DWORDS
|
||
|
+ * that have been transfered by the RXDMA engine
|
||
|
+ */
|
||
|
+ dbg_options = crystalhd_reg_rd(adp, MISC1_DMA_DEBUG_OPTIONS_REG);
|
||
|
+ dbg_options |= 0x10;
|
||
|
+ crystalhd_reg_wr(adp, MISC1_DMA_DEBUG_OPTIONS_REG, dbg_options);
|
||
|
+
|
||
|
+ /* Enable PCI Global Control options */
|
||
|
+ glb_cntrl = crystalhd_reg_rd(adp, MISC2_GLOBAL_CTRL);
|
||
|
+ glb_cntrl |= 0x100;
|
||
|
+ glb_cntrl |= 0x8000;
|
||
|
+ crystalhd_reg_wr(adp, MISC2_GLOBAL_CTRL, glb_cntrl);
|
||
|
+
|
||
|
+ crystalhd_enable_interrupts(adp);
|
||
|
+
|
||
|
+ crystalhd_soft_rst(adp);
|
||
|
+ crystalhd_start_dram(adp);
|
||
|
+ crystalhd_enable_uarts(adp);
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static bool crystalhd_stop_device(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ uint32_t reg;
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_INFO, "Stopping BCM70012 Device\n");
|
||
|
+ /* Clear and disable interrupts */
|
||
|
+ crystalhd_disable_interrupts(adp);
|
||
|
+ crystalhd_clear_errors(adp);
|
||
|
+ crystalhd_clear_interrupts(adp);
|
||
|
+
|
||
|
+ if (!crystalhd_put_in_reset(adp))
|
||
|
+ BCMLOG_ERR("Failed to Put Link To Reset State\n");
|
||
|
+
|
||
|
+ reg = crystalhd_reg_rd(adp, PCIE_DLL_DATA_LINK_CONTROL);
|
||
|
+ reg |= ASPM_L1_ENABLE;
|
||
|
+ crystalhd_reg_wr(adp, PCIE_DLL_DATA_LINK_CONTROL, reg);
|
||
|
+
|
||
|
+ /* Set PCI Clk Req */
|
||
|
+ reg = crystalhd_reg_rd(adp, PCIE_CLK_REQ_REG);
|
||
|
+ reg |= PCI_CLK_REQ_ENABLE;
|
||
|
+ crystalhd_reg_wr(adp, PCIE_CLK_REQ_REG, reg);
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static crystalhd_rx_dma_pkt *crystalhd_hw_alloc_rx_pkt(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+ crystalhd_rx_dma_pkt *temp = NULL;
|
||
|
+
|
||
|
+ if (!hw)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ spin_lock_irqsave(&hw->lock, flags);
|
||
|
+ temp = hw->rx_pkt_pool_head;
|
||
|
+ if (temp) {
|
||
|
+ hw->rx_pkt_pool_head = hw->rx_pkt_pool_head->next;
|
||
|
+ temp->dio_req = NULL;
|
||
|
+ temp->pkt_tag = 0;
|
||
|
+ temp->flags = 0;
|
||
|
+ }
|
||
|
+ spin_unlock_irqrestore(&hw->lock, flags);
|
||
|
+
|
||
|
+ return temp;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_hw_free_rx_pkt(struct crystalhd_hw *hw,
|
||
|
+ crystalhd_rx_dma_pkt *pkt)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+
|
||
|
+ if (!hw || !pkt)
|
||
|
+ return;
|
||
|
+
|
||
|
+ spin_lock_irqsave(&hw->lock, flags);
|
||
|
+ pkt->next = hw->rx_pkt_pool_head;
|
||
|
+ hw->rx_pkt_pool_head = pkt;
|
||
|
+ spin_unlock_irqrestore(&hw->lock, flags);
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Call back from TX - IOQ deletion.
|
||
|
+ *
|
||
|
+ * This routine will release the TX DMA rings allocated
|
||
|
+ * druing setup_dma rings interface.
|
||
|
+ *
|
||
|
+ * Memory is allocated per DMA ring basis. This is just
|
||
|
+ * a place holder to be able to create the dio queues.
|
||
|
+ */
|
||
|
+static void crystalhd_tx_desc_rel_call_back(void *context, void *data)
|
||
|
+{
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Rx Packet release callback..
|
||
|
+ *
|
||
|
+ * Release All user mapped capture buffers and Our DMA packets
|
||
|
+ * back to our free pool. The actual cleanup of the DMA
|
||
|
+ * ring descriptors happen during dma ring release.
|
||
|
+ */
|
||
|
+static void crystalhd_rx_pkt_rel_call_back(void *context, void *data)
|
||
|
+{
|
||
|
+ struct crystalhd_hw *hw = (struct crystalhd_hw *)context;
|
||
|
+ crystalhd_rx_dma_pkt *pkt = (crystalhd_rx_dma_pkt *)data;
|
||
|
+
|
||
|
+ if (!pkt || !hw) {
|
||
|
+ BCMLOG_ERR("Invalid arg - %p %p\n", hw, pkt);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (pkt->dio_req)
|
||
|
+ crystalhd_unmap_dio(hw->adp, pkt->dio_req);
|
||
|
+ else
|
||
|
+ BCMLOG_ERR("Missing dio_req: 0x%x\n", pkt->pkt_tag);
|
||
|
+
|
||
|
+ crystalhd_hw_free_rx_pkt(hw, pkt);
|
||
|
+}
|
||
|
+
|
||
|
+#define crystalhd_hw_delete_ioq(adp, q) \
|
||
|
+ if (q) { \
|
||
|
+ crystalhd_delete_dioq(adp, q); \
|
||
|
+ q = NULL; \
|
||
|
+ }
|
||
|
+
|
||
|
+static void crystalhd_hw_delete_ioqs(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ if (!hw)
|
||
|
+ return;
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DBG, "Deleting IOQs \n");
|
||
|
+ crystalhd_hw_delete_ioq(hw->adp, hw->tx_actq);
|
||
|
+ crystalhd_hw_delete_ioq(hw->adp, hw->tx_freeq);
|
||
|
+ crystalhd_hw_delete_ioq(hw->adp, hw->rx_actq);
|
||
|
+ crystalhd_hw_delete_ioq(hw->adp, hw->rx_freeq);
|
||
|
+ crystalhd_hw_delete_ioq(hw->adp, hw->rx_rdyq);
|
||
|
+}
|
||
|
+
|
||
|
+#define crystalhd_hw_create_ioq(sts, hw, q, cb) \
|
||
|
+do { \
|
||
|
+ sts = crystalhd_create_dioq(hw->adp, &q, cb, hw); \
|
||
|
+ if (sts != BC_STS_SUCCESS) \
|
||
|
+ goto hw_create_ioq_err; \
|
||
|
+} while (0)
|
||
|
+
|
||
|
+/*
|
||
|
+ * Create IOQs..
|
||
|
+ *
|
||
|
+ * TX - Active & Free
|
||
|
+ * RX - Active, Ready and Free.
|
||
|
+ */
|
||
|
+static BC_STATUS crystalhd_hw_create_ioqs(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (!hw) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_hw_create_ioq(sts, hw, hw->tx_freeq,
|
||
|
+ crystalhd_tx_desc_rel_call_back);
|
||
|
+ crystalhd_hw_create_ioq(sts, hw, hw->tx_actq,
|
||
|
+ crystalhd_tx_desc_rel_call_back);
|
||
|
+
|
||
|
+ crystalhd_hw_create_ioq(sts, hw, hw->rx_freeq,
|
||
|
+ crystalhd_rx_pkt_rel_call_back);
|
||
|
+ crystalhd_hw_create_ioq(sts, hw, hw->rx_rdyq,
|
||
|
+ crystalhd_rx_pkt_rel_call_back);
|
||
|
+ crystalhd_hw_create_ioq(sts, hw, hw->rx_actq,
|
||
|
+ crystalhd_rx_pkt_rel_call_back);
|
||
|
+
|
||
|
+ return sts;
|
||
|
+
|
||
|
+hw_create_ioq_err:
|
||
|
+ crystalhd_hw_delete_ioqs(hw);
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static bool crystalhd_code_in_full(struct crystalhd_adp *adp, uint32_t needed_sz,
|
||
|
+ bool b_188_byte_pkts, uint8_t flags)
|
||
|
+{
|
||
|
+ uint32_t base, end, writep, readp;
|
||
|
+ uint32_t cpbSize, cpbFullness, fifoSize;
|
||
|
+
|
||
|
+ if (flags & 0x02) { /* ASF Bit is set */
|
||
|
+ base = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Base);
|
||
|
+ end = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2End);
|
||
|
+ writep = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Wrptr);
|
||
|
+ readp = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Rdptr);
|
||
|
+ } else if (b_188_byte_pkts) { /*Encrypted 188 byte packets*/
|
||
|
+ base = bc_dec_reg_rd(adp, REG_Dec_TsUser0Base);
|
||
|
+ end = bc_dec_reg_rd(adp, REG_Dec_TsUser0End);
|
||
|
+ writep = bc_dec_reg_rd(adp, REG_Dec_TsUser0Wrptr);
|
||
|
+ readp = bc_dec_reg_rd(adp, REG_Dec_TsUser0Rdptr);
|
||
|
+ } else {
|
||
|
+ base = bc_dec_reg_rd(adp, REG_DecCA_RegCinBase);
|
||
|
+ end = bc_dec_reg_rd(adp, REG_DecCA_RegCinEnd);
|
||
|
+ writep = bc_dec_reg_rd(adp, REG_DecCA_RegCinWrPtr);
|
||
|
+ readp = bc_dec_reg_rd(adp, REG_DecCA_RegCinRdPtr);
|
||
|
+ }
|
||
|
+
|
||
|
+ cpbSize = end - base;
|
||
|
+ if (writep >= readp)
|
||
|
+ cpbFullness = writep - readp;
|
||
|
+ else
|
||
|
+ cpbFullness = (end - base) - (readp - writep);
|
||
|
+
|
||
|
+ fifoSize = cpbSize - cpbFullness;
|
||
|
+
|
||
|
+ if (fifoSize < BC_INFIFO_THRESHOLD)
|
||
|
+ return true;
|
||
|
+
|
||
|
+ if (needed_sz > (fifoSize - BC_INFIFO_THRESHOLD))
|
||
|
+ return true;
|
||
|
+
|
||
|
+ return false;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS crystalhd_hw_tx_req_complete(struct crystalhd_hw *hw,
|
||
|
+ uint32_t list_id, BC_STATUS cs)
|
||
|
+{
|
||
|
+ tx_dma_pkt *tx_req;
|
||
|
+
|
||
|
+ if (!hw || !list_id) {
|
||
|
+ BCMLOG_ERR("Invalid Arg..\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ hw->pwr_lock--;
|
||
|
+
|
||
|
+ tx_req = (tx_dma_pkt *)crystalhd_dioq_find_and_fetch(hw->tx_actq, list_id);
|
||
|
+ if (!tx_req) {
|
||
|
+ if (cs != BC_STS_IO_USER_ABORT)
|
||
|
+ BCMLOG_ERR("Find and Fetch Did not find req\n");
|
||
|
+ return BC_STS_NO_DATA;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (tx_req->call_back) {
|
||
|
+ tx_req->call_back(tx_req->dio_req, tx_req->cb_event, cs);
|
||
|
+ tx_req->dio_req = NULL;
|
||
|
+ tx_req->cb_event = NULL;
|
||
|
+ tx_req->call_back = NULL;
|
||
|
+ } else {
|
||
|
+ BCMLOG(BCMLOG_DBG, "Missing Tx Callback - %X\n",
|
||
|
+ tx_req->list_tag);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Now put back the tx_list back in FreeQ */
|
||
|
+ tx_req->list_tag = 0;
|
||
|
+
|
||
|
+ return crystalhd_dioq_add(hw->tx_freeq, tx_req, false, 0);
|
||
|
+}
|
||
|
+
|
||
|
+static bool crystalhd_tx_list0_handler(struct crystalhd_hw *hw, uint32_t err_sts)
|
||
|
+{
|
||
|
+ uint32_t err_mask, tmp;
|
||
|
+ unsigned long flags = 0;
|
||
|
+
|
||
|
+ err_mask = MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_MASK |
|
||
|
+ MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_MASK |
|
||
|
+ MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK;
|
||
|
+
|
||
|
+ if (!(err_sts & err_mask))
|
||
|
+ return false;
|
||
|
+
|
||
|
+ BCMLOG_ERR("Error on Tx-L0 %x \n", err_sts);
|
||
|
+
|
||
|
+ tmp = err_mask;
|
||
|
+
|
||
|
+ if (err_sts & MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK)
|
||
|
+ tmp &= ~MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK;
|
||
|
+
|
||
|
+ if (tmp) {
|
||
|
+ spin_lock_irqsave(&hw->lock, flags);
|
||
|
+ /* reset list index.*/
|
||
|
+ hw->tx_list_post_index = 0;
|
||
|
+ spin_unlock_irqrestore(&hw->lock, flags);
|
||
|
+ }
|
||
|
+
|
||
|
+ tmp = err_sts & err_mask;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_TX_DMA_ERROR_STATUS, tmp);
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static bool crystalhd_tx_list1_handler(struct crystalhd_hw *hw, uint32_t err_sts)
|
||
|
+{
|
||
|
+ uint32_t err_mask, tmp;
|
||
|
+ unsigned long flags = 0;
|
||
|
+
|
||
|
+ err_mask = MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_MASK |
|
||
|
+ MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_MASK |
|
||
|
+ MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK;
|
||
|
+
|
||
|
+ if (!(err_sts & err_mask))
|
||
|
+ return false;
|
||
|
+
|
||
|
+ BCMLOG_ERR("Error on Tx-L1 %x \n", err_sts);
|
||
|
+
|
||
|
+ tmp = err_mask;
|
||
|
+
|
||
|
+ if (err_sts & MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK)
|
||
|
+ tmp &= ~MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK;
|
||
|
+
|
||
|
+ if (tmp) {
|
||
|
+ spin_lock_irqsave(&hw->lock, flags);
|
||
|
+ /* reset list index.*/
|
||
|
+ hw->tx_list_post_index = 0;
|
||
|
+ spin_unlock_irqrestore(&hw->lock, flags);
|
||
|
+ }
|
||
|
+
|
||
|
+ tmp = err_sts & err_mask;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_TX_DMA_ERROR_STATUS, tmp);
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_tx_isr(struct crystalhd_hw *hw, uint32_t int_sts)
|
||
|
+{
|
||
|
+ uint32_t err_sts;
|
||
|
+
|
||
|
+ if (int_sts & INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_MASK)
|
||
|
+ crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 0,
|
||
|
+ BC_STS_SUCCESS);
|
||
|
+
|
||
|
+ if (int_sts & INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_MASK)
|
||
|
+ crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 1,
|
||
|
+ BC_STS_SUCCESS);
|
||
|
+
|
||
|
+ if (!(int_sts & (INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_MASK |
|
||
|
+ INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_MASK))) {
|
||
|
+ /* No error mask set.. */
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Handle Tx errors. */
|
||
|
+ err_sts = crystalhd_reg_rd(hw->adp, MISC1_TX_DMA_ERROR_STATUS);
|
||
|
+
|
||
|
+ if (crystalhd_tx_list0_handler(hw, err_sts))
|
||
|
+ crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 0,
|
||
|
+ BC_STS_ERROR);
|
||
|
+
|
||
|
+ if (crystalhd_tx_list1_handler(hw, err_sts))
|
||
|
+ crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 1,
|
||
|
+ BC_STS_ERROR);
|
||
|
+
|
||
|
+ hw->stats.tx_errors++;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_hw_dump_desc(pdma_descriptor p_dma_desc,
|
||
|
+ uint32_t ul_desc_index, uint32_t cnt)
|
||
|
+{
|
||
|
+ uint32_t ix, ll = 0;
|
||
|
+
|
||
|
+ if (!p_dma_desc || !cnt)
|
||
|
+ return;
|
||
|
+
|
||
|
+ /* FIXME: jarod: perhaps a modparam desc_debug to enable this, rather than
|
||
|
+ * setting ll (log level, I presume) to non-zero? */
|
||
|
+ if (!ll)
|
||
|
+ return;
|
||
|
+
|
||
|
+ for (ix = ul_desc_index; ix < (ul_desc_index + cnt); ix++) {
|
||
|
+ BCMLOG(ll, "%s[%d] Buff[%x:%x] Next:[%x:%x] XferSz:%x Intr:%x,Last:%x\n",
|
||
|
+ ((p_dma_desc[ul_desc_index].dma_dir) ? "TDesc" : "RDesc"),
|
||
|
+ ul_desc_index,
|
||
|
+ p_dma_desc[ul_desc_index].buff_addr_high,
|
||
|
+ p_dma_desc[ul_desc_index].buff_addr_low,
|
||
|
+ p_dma_desc[ul_desc_index].next_desc_addr_high,
|
||
|
+ p_dma_desc[ul_desc_index].next_desc_addr_low,
|
||
|
+ p_dma_desc[ul_desc_index].xfer_size,
|
||
|
+ p_dma_desc[ul_desc_index].intr_enable,
|
||
|
+ p_dma_desc[ul_desc_index].last_rec_indicator);
|
||
|
+ }
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS crystalhd_hw_fill_desc(crystalhd_dio_req *ioreq,
|
||
|
+ dma_descriptor *desc,
|
||
|
+ dma_addr_t desc_paddr_base,
|
||
|
+ uint32_t sg_cnt, uint32_t sg_st_ix,
|
||
|
+ uint32_t sg_st_off, uint32_t xfr_sz)
|
||
|
+{
|
||
|
+ uint32_t count = 0, ix = 0, sg_ix = 0, len = 0, last_desc_ix = 0;
|
||
|
+ dma_addr_t desc_phy_addr = desc_paddr_base;
|
||
|
+ addr_64 addr_temp;
|
||
|
+
|
||
|
+ if (!ioreq || !desc || !desc_paddr_base || !xfr_sz ||
|
||
|
+ (!sg_cnt && !ioreq->uinfo.dir_tx)) {
|
||
|
+ BCMLOG_ERR("Invalid Args\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (ix = 0; ix < sg_cnt; ix++) {
|
||
|
+
|
||
|
+ /* Setup SGLE index. */
|
||
|
+ sg_ix = ix + sg_st_ix;
|
||
|
+
|
||
|
+ /* Get SGLE length */
|
||
|
+ len = crystalhd_get_sgle_len(ioreq, sg_ix);
|
||
|
+ if (len % 4) {
|
||
|
+ BCMLOG_ERR(" len in sg %d %d %d\n", len, sg_ix, sg_cnt);
|
||
|
+ return BC_STS_NOT_IMPL;
|
||
|
+ }
|
||
|
+ /* Setup DMA desc with Phy addr & Length at current index. */
|
||
|
+ addr_temp.full_addr = crystalhd_get_sgle_paddr(ioreq, sg_ix);
|
||
|
+ if (sg_ix == sg_st_ix) {
|
||
|
+ addr_temp.full_addr += sg_st_off;
|
||
|
+ len -= sg_st_off;
|
||
|
+ }
|
||
|
+ memset(&desc[ix], 0, sizeof(desc[ix]));
|
||
|
+ desc[ix].buff_addr_low = addr_temp.low_part;
|
||
|
+ desc[ix].buff_addr_high = addr_temp.high_part;
|
||
|
+ desc[ix].dma_dir = ioreq->uinfo.dir_tx;
|
||
|
+
|
||
|
+ /* Chain DMA descriptor. */
|
||
|
+ addr_temp.full_addr = desc_phy_addr + sizeof(dma_descriptor);
|
||
|
+ desc[ix].next_desc_addr_low = addr_temp.low_part;
|
||
|
+ desc[ix].next_desc_addr_high = addr_temp.high_part;
|
||
|
+
|
||
|
+ if ((count + len) > xfr_sz)
|
||
|
+ len = xfr_sz - count;
|
||
|
+
|
||
|
+ /* Debug.. */
|
||
|
+ if ((!len) || (len > crystalhd_get_sgle_len(ioreq, sg_ix))) {
|
||
|
+ BCMLOG_ERR("inv-len(%x) Ix(%d) count:%x xfr_sz:%x sg_cnt:%d\n",
|
||
|
+ len, ix, count, xfr_sz, sg_cnt);
|
||
|
+ return BC_STS_ERROR;
|
||
|
+ }
|
||
|
+ /* Length expects Multiple of 4 */
|
||
|
+ desc[ix].xfer_size = (len / 4);
|
||
|
+
|
||
|
+ crystalhd_hw_dump_desc(desc, ix, 1);
|
||
|
+
|
||
|
+ count += len;
|
||
|
+ desc_phy_addr += sizeof(dma_descriptor);
|
||
|
+ }
|
||
|
+
|
||
|
+ last_desc_ix = ix - 1;
|
||
|
+
|
||
|
+ if (ioreq->fb_size) {
|
||
|
+ memset(&desc[ix], 0, sizeof(desc[ix]));
|
||
|
+ addr_temp.full_addr = ioreq->fb_pa;
|
||
|
+ desc[ix].buff_addr_low = addr_temp.low_part;
|
||
|
+ desc[ix].buff_addr_high = addr_temp.high_part;
|
||
|
+ desc[ix].dma_dir = ioreq->uinfo.dir_tx;
|
||
|
+ desc[ix].xfer_size = 1;
|
||
|
+ desc[ix].fill_bytes = 4 - ioreq->fb_size;
|
||
|
+ count += ioreq->fb_size;
|
||
|
+ last_desc_ix++;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* setup last descriptor..*/
|
||
|
+ desc[last_desc_ix].last_rec_indicator = 1;
|
||
|
+ desc[last_desc_ix].next_desc_addr_low = 0;
|
||
|
+ desc[last_desc_ix].next_desc_addr_high = 0;
|
||
|
+ desc[last_desc_ix].intr_enable = 1;
|
||
|
+
|
||
|
+ crystalhd_hw_dump_desc(desc, last_desc_ix, 1);
|
||
|
+
|
||
|
+ if (count != xfr_sz) {
|
||
|
+ BCMLOG_ERR("interal error sz curr:%x exp:%x\n", count, xfr_sz);
|
||
|
+ return BC_STS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS crystalhd_xlat_sgl_to_dma_desc(crystalhd_dio_req *ioreq,
|
||
|
+ pdma_desc_mem pdesc_mem,
|
||
|
+ uint32_t *uv_desc_index)
|
||
|
+{
|
||
|
+ dma_descriptor *desc = NULL;
|
||
|
+ dma_addr_t desc_paddr_base = 0;
|
||
|
+ uint32_t sg_cnt = 0, sg_st_ix = 0, sg_st_off = 0;
|
||
|
+ uint32_t xfr_sz = 0;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ /* Check params.. */
|
||
|
+ if (!ioreq || !pdesc_mem || !uv_desc_index) {
|
||
|
+ BCMLOG_ERR("Invalid Args\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!pdesc_mem->sz || !pdesc_mem->pdma_desc_start ||
|
||
|
+ !ioreq->sg || (!ioreq->sg_cnt && !ioreq->uinfo.dir_tx)) {
|
||
|
+ BCMLOG_ERR("Invalid Args\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if ((ioreq->uinfo.dir_tx) && (ioreq->uinfo.uv_offset)) {
|
||
|
+ BCMLOG_ERR("UV offset for TX??\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+
|
||
|
+ }
|
||
|
+
|
||
|
+ desc = pdesc_mem->pdma_desc_start;
|
||
|
+ desc_paddr_base = pdesc_mem->phy_addr;
|
||
|
+
|
||
|
+ if (ioreq->uinfo.dir_tx || (ioreq->uinfo.uv_offset == 0)) {
|
||
|
+ sg_cnt = ioreq->sg_cnt;
|
||
|
+ xfr_sz = ioreq->uinfo.xfr_len;
|
||
|
+ } else {
|
||
|
+ sg_cnt = ioreq->uinfo.uv_sg_ix + 1;
|
||
|
+ xfr_sz = ioreq->uinfo.uv_offset;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_hw_fill_desc(ioreq, desc, desc_paddr_base, sg_cnt,
|
||
|
+ sg_st_ix, sg_st_off, xfr_sz);
|
||
|
+
|
||
|
+ if ((sts != BC_STS_SUCCESS) || !ioreq->uinfo.uv_offset)
|
||
|
+ return sts;
|
||
|
+
|
||
|
+ /* Prepare for UV mapping.. */
|
||
|
+ desc = &pdesc_mem->pdma_desc_start[sg_cnt];
|
||
|
+ desc_paddr_base = pdesc_mem->phy_addr +
|
||
|
+ (sg_cnt * sizeof(dma_descriptor));
|
||
|
+
|
||
|
+ /* Done with desc addr.. now update sg stuff.*/
|
||
|
+ sg_cnt = ioreq->sg_cnt - ioreq->uinfo.uv_sg_ix;
|
||
|
+ xfr_sz = ioreq->uinfo.xfr_len - ioreq->uinfo.uv_offset;
|
||
|
+ sg_st_ix = ioreq->uinfo.uv_sg_ix;
|
||
|
+ sg_st_off = ioreq->uinfo.uv_sg_off;
|
||
|
+
|
||
|
+ sts = crystalhd_hw_fill_desc(ioreq, desc, desc_paddr_base, sg_cnt,
|
||
|
+ sg_st_ix, sg_st_off, xfr_sz);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ return sts;
|
||
|
+
|
||
|
+ *uv_desc_index = sg_st_ix;
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_start_tx_dma_engine(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ uint32_t dma_cntrl;
|
||
|
+
|
||
|
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS);
|
||
|
+ if (!(dma_cntrl & DMA_START_BIT)) {
|
||
|
+ dma_cntrl |= DMA_START_BIT;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS,
|
||
|
+ dma_cntrl);
|
||
|
+ }
|
||
|
+
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+/* _CHECK_THIS_
|
||
|
+ *
|
||
|
+ * Verify if the Stop generates a completion interrupt or not.
|
||
|
+ * if it does not generate an interrupt, then add polling here.
|
||
|
+ */
|
||
|
+static BC_STATUS crystalhd_stop_tx_dma_engine(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ uint32_t dma_cntrl, cnt = 30;
|
||
|
+ uint32_t l1 = 1, l2 = 1;
|
||
|
+ unsigned long flags = 0;
|
||
|
+
|
||
|
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS);
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DBG, "Stopping TX DMA Engine..\n");
|
||
|
+
|
||
|
+ /* FIXME: jarod: invert dma_ctrl and check bit? or are there missing parens? */
|
||
|
+ if (!dma_cntrl & DMA_START_BIT) {
|
||
|
+ BCMLOG(BCMLOG_DBG, "Already Stopped\n");
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_disable_interrupts(hw->adp);
|
||
|
+
|
||
|
+ /* Issue stop to HW */
|
||
|
+ /* This bit when set gave problems. Please check*/
|
||
|
+ dma_cntrl &= ~DMA_START_BIT;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DBG, "Cleared the DMA Start bit\n");
|
||
|
+
|
||
|
+ /* Poll for 3seconds (30 * 100ms) on both the lists..*/
|
||
|
+ while ((l1 || l2) && cnt) {
|
||
|
+
|
||
|
+ if (l1) {
|
||
|
+ l1 = crystalhd_reg_rd(hw->adp, MISC1_TX_FIRST_DESC_L_ADDR_LIST0);
|
||
|
+ l1 &= DMA_START_BIT;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (l2) {
|
||
|
+ l2 = crystalhd_reg_rd(hw->adp, MISC1_TX_FIRST_DESC_L_ADDR_LIST1);
|
||
|
+ l2 &= DMA_START_BIT;
|
||
|
+ }
|
||
|
+
|
||
|
+ msleep_interruptible(100);
|
||
|
+
|
||
|
+ cnt--;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!cnt) {
|
||
|
+ BCMLOG_ERR("Failed to stop TX DMA.. l1 %d, l2 %d\n", l1, l2);
|
||
|
+ crystalhd_enable_interrupts(hw->adp);
|
||
|
+ return BC_STS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ spin_lock_irqsave(&hw->lock, flags);
|
||
|
+ hw->tx_list_post_index = 0;
|
||
|
+ spin_unlock_irqrestore(&hw->lock, flags);
|
||
|
+ BCMLOG(BCMLOG_DBG, "stopped TX DMA..\n");
|
||
|
+ crystalhd_enable_interrupts(hw->adp);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static uint32_t crystalhd_get_pib_avail_cnt(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ /*
|
||
|
+ * Position of the PIB Entries can be found at
|
||
|
+ * 0th and the 1st location of the Circular list.
|
||
|
+ */
|
||
|
+ uint32_t Q_addr;
|
||
|
+ uint32_t pib_cnt, r_offset, w_offset;
|
||
|
+
|
||
|
+ Q_addr = hw->pib_del_Q_addr;
|
||
|
+
|
||
|
+ /* Get the Read Pointer */
|
||
|
+ crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
|
||
|
+
|
||
|
+ /* Get the Write Pointer */
|
||
|
+ crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
|
||
|
+
|
||
|
+ if (r_offset == w_offset)
|
||
|
+ return 0; /* Queue is empty */
|
||
|
+
|
||
|
+ if (w_offset > r_offset)
|
||
|
+ pib_cnt = w_offset - r_offset;
|
||
|
+ else
|
||
|
+ pib_cnt = (w_offset + MAX_PIB_Q_DEPTH) -
|
||
|
+ (r_offset + MIN_PIB_Q_DEPTH);
|
||
|
+
|
||
|
+ if (pib_cnt > MAX_PIB_Q_DEPTH) {
|
||
|
+ BCMLOG_ERR("Invalid PIB Count (%u)\n", pib_cnt);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ return pib_cnt;
|
||
|
+}
|
||
|
+
|
||
|
+static uint32_t crystalhd_get_addr_from_pib_Q(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ uint32_t Q_addr;
|
||
|
+ uint32_t addr_entry, r_offset, w_offset;
|
||
|
+
|
||
|
+ Q_addr = hw->pib_del_Q_addr;
|
||
|
+
|
||
|
+ /* Get the Read Pointer 0Th Location is Read Pointer */
|
||
|
+ crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
|
||
|
+
|
||
|
+ /* Get the Write Pointer 1st Location is Write pointer */
|
||
|
+ crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
|
||
|
+
|
||
|
+ /* Queue is empty */
|
||
|
+ if (r_offset == w_offset)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ if ((r_offset < MIN_PIB_Q_DEPTH) || (r_offset >= MAX_PIB_Q_DEPTH))
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ /* Get the Actual Address of the PIB */
|
||
|
+ crystalhd_mem_rd(hw->adp, Q_addr + (r_offset * sizeof(uint32_t)),
|
||
|
+ 1, &addr_entry);
|
||
|
+
|
||
|
+ /* Increment the Read Pointer */
|
||
|
+ r_offset++;
|
||
|
+
|
||
|
+ if (MAX_PIB_Q_DEPTH == r_offset)
|
||
|
+ r_offset = MIN_PIB_Q_DEPTH;
|
||
|
+
|
||
|
+ /* Write back the read pointer to It's Location */
|
||
|
+ crystalhd_mem_wr(hw->adp, Q_addr, 1, &r_offset);
|
||
|
+
|
||
|
+ return addr_entry;
|
||
|
+}
|
||
|
+
|
||
|
+static bool crystalhd_rel_addr_to_pib_Q(struct crystalhd_hw *hw, uint32_t addr_to_rel)
|
||
|
+{
|
||
|
+ uint32_t Q_addr;
|
||
|
+ uint32_t r_offset, w_offset, n_offset;
|
||
|
+
|
||
|
+ Q_addr = hw->pib_rel_Q_addr;
|
||
|
+
|
||
|
+ /* Get the Read Pointer */
|
||
|
+ crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
|
||
|
+
|
||
|
+ /* Get the Write Pointer */
|
||
|
+ crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
|
||
|
+
|
||
|
+ if ((r_offset < MIN_PIB_Q_DEPTH) ||
|
||
|
+ (r_offset >= MAX_PIB_Q_DEPTH))
|
||
|
+ return false;
|
||
|
+
|
||
|
+ n_offset = w_offset + 1;
|
||
|
+
|
||
|
+ if (MAX_PIB_Q_DEPTH == n_offset)
|
||
|
+ n_offset = MIN_PIB_Q_DEPTH;
|
||
|
+
|
||
|
+ if (r_offset == n_offset)
|
||
|
+ return false; /* should never happen */
|
||
|
+
|
||
|
+ /* Write the DRAM ADDR to the Queue at Next Offset */
|
||
|
+ crystalhd_mem_wr(hw->adp, Q_addr + (w_offset * sizeof(uint32_t)),
|
||
|
+ 1, &addr_to_rel);
|
||
|
+
|
||
|
+ /* Put the New value of the write pointer in Queue */
|
||
|
+ crystalhd_mem_wr(hw->adp, Q_addr + sizeof(uint32_t), 1, &n_offset);
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static void cpy_pib_to_app(C011_PIB *src_pib, BC_PIC_INFO_BLOCK *dst_pib)
|
||
|
+{
|
||
|
+ if (!src_pib || !dst_pib) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ dst_pib->timeStamp = 0;
|
||
|
+ dst_pib->picture_number = src_pib->ppb.picture_number;
|
||
|
+ dst_pib->width = src_pib->ppb.width;
|
||
|
+ dst_pib->height = src_pib->ppb.height;
|
||
|
+ dst_pib->chroma_format = src_pib->ppb.chroma_format;
|
||
|
+ dst_pib->pulldown = src_pib->ppb.pulldown;
|
||
|
+ dst_pib->flags = src_pib->ppb.flags;
|
||
|
+ dst_pib->sess_num = src_pib->ptsStcOffset;
|
||
|
+ dst_pib->aspect_ratio = src_pib->ppb.aspect_ratio;
|
||
|
+ dst_pib->colour_primaries = src_pib->ppb.colour_primaries;
|
||
|
+ dst_pib->picture_meta_payload = src_pib->ppb.picture_meta_payload;
|
||
|
+ dst_pib->frame_rate = src_pib->resolution ;
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_hw_proc_pib(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ unsigned int cnt;
|
||
|
+ C011_PIB src_pib;
|
||
|
+ uint32_t pib_addr, pib_cnt;
|
||
|
+ BC_PIC_INFO_BLOCK *AppPib;
|
||
|
+ crystalhd_rx_dma_pkt *rx_pkt = NULL;
|
||
|
+
|
||
|
+ pib_cnt = crystalhd_get_pib_avail_cnt(hw);
|
||
|
+
|
||
|
+ if (!pib_cnt)
|
||
|
+ return;
|
||
|
+
|
||
|
+ for (cnt = 0; cnt < pib_cnt; cnt++) {
|
||
|
+
|
||
|
+ pib_addr = crystalhd_get_addr_from_pib_Q(hw);
|
||
|
+ crystalhd_mem_rd(hw->adp, pib_addr, sizeof(C011_PIB) / 4,
|
||
|
+ (uint32_t *)&src_pib);
|
||
|
+
|
||
|
+ if (src_pib.bFormatChange) {
|
||
|
+ rx_pkt = (crystalhd_rx_dma_pkt *)crystalhd_dioq_fetch(hw->rx_freeq);
|
||
|
+ if (!rx_pkt)
|
||
|
+ return;
|
||
|
+ rx_pkt->flags = 0;
|
||
|
+ rx_pkt->flags |= COMP_FLAG_PIB_VALID | COMP_FLAG_FMT_CHANGE;
|
||
|
+ AppPib = &rx_pkt->pib;
|
||
|
+ cpy_pib_to_app(&src_pib, AppPib);
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DBG,
|
||
|
+ "App PIB:%x %x %x %x %x %x %x %x %x %x\n",
|
||
|
+ rx_pkt->pib.picture_number,
|
||
|
+ rx_pkt->pib.aspect_ratio,
|
||
|
+ rx_pkt->pib.chroma_format,
|
||
|
+ rx_pkt->pib.colour_primaries,
|
||
|
+ rx_pkt->pib.frame_rate,
|
||
|
+ rx_pkt->pib.height,
|
||
|
+ rx_pkt->pib.height,
|
||
|
+ rx_pkt->pib.n_drop,
|
||
|
+ rx_pkt->pib.pulldown,
|
||
|
+ rx_pkt->pib.ycom);
|
||
|
+
|
||
|
+ crystalhd_dioq_add(hw->rx_rdyq, (void *)rx_pkt, true, rx_pkt->pkt_tag);
|
||
|
+
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_rel_addr_to_pib_Q(hw, pib_addr);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_start_rx_dma_engine(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ uint32_t dma_cntrl;
|
||
|
+
|
||
|
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
|
||
|
+ if (!(dma_cntrl & DMA_START_BIT)) {
|
||
|
+ dma_cntrl |= DMA_START_BIT;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
|
||
|
+ }
|
||
|
+
|
||
|
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
|
||
|
+ if (!(dma_cntrl & DMA_START_BIT)) {
|
||
|
+ dma_cntrl |= DMA_START_BIT;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
|
||
|
+ }
|
||
|
+
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_stop_rx_dma_engine(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ uint32_t dma_cntrl = 0, count = 30;
|
||
|
+ uint32_t l0y = 1, l0uv = 1, l1y = 1, l1uv = 1;
|
||
|
+
|
||
|
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
|
||
|
+ if ((dma_cntrl & DMA_START_BIT)) {
|
||
|
+ dma_cntrl &= ~DMA_START_BIT;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
|
||
|
+ }
|
||
|
+
|
||
|
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
|
||
|
+ if ((dma_cntrl & DMA_START_BIT)) {
|
||
|
+ dma_cntrl &= ~DMA_START_BIT;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Poll for 3seconds (30 * 100ms) on both the lists..*/
|
||
|
+ while ((l0y || l0uv || l1y || l1uv) && count) {
|
||
|
+
|
||
|
+ if (l0y) {
|
||
|
+ l0y = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0);
|
||
|
+ l0y &= DMA_START_BIT;
|
||
|
+ if (!l0y) {
|
||
|
+ hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (l1y) {
|
||
|
+ l1y = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1);
|
||
|
+ l1y &= DMA_START_BIT;
|
||
|
+ if (!l1y) {
|
||
|
+ hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (l0uv) {
|
||
|
+ l0uv = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0);
|
||
|
+ l0uv &= DMA_START_BIT;
|
||
|
+ if (!l0uv) {
|
||
|
+ hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (l1uv) {
|
||
|
+ l1uv = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1);
|
||
|
+ l1uv &= DMA_START_BIT;
|
||
|
+ if (!l1uv) {
|
||
|
+ hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ msleep_interruptible(100);
|
||
|
+ count--;
|
||
|
+ }
|
||
|
+
|
||
|
+ hw->rx_list_post_index = 0;
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_SSTEP, "Capture Stop: %d List0:Sts:%x List1:Sts:%x\n",
|
||
|
+ count, hw->rx_list_sts[0], hw->rx_list_sts[1]);
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS crystalhd_hw_prog_rxdma(struct crystalhd_hw *hw, crystalhd_rx_dma_pkt *rx_pkt)
|
||
|
+{
|
||
|
+ uint32_t y_low_addr_reg, y_high_addr_reg;
|
||
|
+ uint32_t uv_low_addr_reg, uv_high_addr_reg;
|
||
|
+ addr_64 desc_addr;
|
||
|
+ unsigned long flags;
|
||
|
+
|
||
|
+ if (!hw || !rx_pkt) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (hw->rx_list_post_index >= DMA_ENGINE_CNT) {
|
||
|
+ BCMLOG_ERR("List Out Of bounds %x\n", hw->rx_list_post_index);
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ spin_lock_irqsave(&hw->rx_lock, flags);
|
||
|
+ /* FIXME: jarod: sts_free is an enum for 0, in crystalhd_hw.h... yuk... */
|
||
|
+ if (sts_free != hw->rx_list_sts[hw->rx_list_post_index]) {
|
||
|
+ spin_unlock_irqrestore(&hw->rx_lock, flags);
|
||
|
+ return BC_STS_BUSY;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!hw->rx_list_post_index) {
|
||
|
+ y_low_addr_reg = MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0;
|
||
|
+ y_high_addr_reg = MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST0;
|
||
|
+ uv_low_addr_reg = MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0;
|
||
|
+ uv_high_addr_reg = MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST0;
|
||
|
+ } else {
|
||
|
+ y_low_addr_reg = MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1;
|
||
|
+ y_high_addr_reg = MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST1;
|
||
|
+ uv_low_addr_reg = MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1;
|
||
|
+ uv_high_addr_reg = MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST1;
|
||
|
+ }
|
||
|
+ rx_pkt->pkt_tag = hw->rx_pkt_tag_seed + hw->rx_list_post_index;
|
||
|
+ hw->rx_list_sts[hw->rx_list_post_index] |= rx_waiting_y_intr;
|
||
|
+ if (rx_pkt->uv_phy_addr)
|
||
|
+ hw->rx_list_sts[hw->rx_list_post_index] |= rx_waiting_uv_intr;
|
||
|
+ hw->rx_list_post_index = (hw->rx_list_post_index + 1) % DMA_ENGINE_CNT;
|
||
|
+ spin_unlock_irqrestore(&hw->rx_lock, flags);
|
||
|
+
|
||
|
+ crystalhd_dioq_add(hw->rx_actq, (void *)rx_pkt, false, rx_pkt->pkt_tag);
|
||
|
+
|
||
|
+ crystalhd_start_rx_dma_engine(hw);
|
||
|
+ /* Program the Y descriptor */
|
||
|
+ desc_addr.full_addr = rx_pkt->desc_mem.phy_addr;
|
||
|
+ crystalhd_reg_wr(hw->adp, y_high_addr_reg, desc_addr.high_part);
|
||
|
+ crystalhd_reg_wr(hw->adp, y_low_addr_reg, desc_addr.low_part | 0x01);
|
||
|
+
|
||
|
+ if (rx_pkt->uv_phy_addr) {
|
||
|
+ /* Program the UV descriptor */
|
||
|
+ desc_addr.full_addr = rx_pkt->uv_phy_addr;
|
||
|
+ crystalhd_reg_wr(hw->adp, uv_high_addr_reg, desc_addr.high_part);
|
||
|
+ crystalhd_reg_wr(hw->adp, uv_low_addr_reg, desc_addr.low_part | 0x01);
|
||
|
+ }
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS crystalhd_hw_post_cap_buff(struct crystalhd_hw *hw,
|
||
|
+ crystalhd_rx_dma_pkt *rx_pkt)
|
||
|
+{
|
||
|
+ BC_STATUS sts = crystalhd_hw_prog_rxdma(hw, rx_pkt);
|
||
|
+
|
||
|
+ if (sts == BC_STS_BUSY)
|
||
|
+ crystalhd_dioq_add(hw->rx_freeq, (void *)rx_pkt,
|
||
|
+ false, rx_pkt->pkt_tag);
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_get_dnsz(struct crystalhd_hw *hw, uint32_t list_index,
|
||
|
+ uint32_t *y_dw_dnsz, uint32_t *uv_dw_dnsz)
|
||
|
+{
|
||
|
+ uint32_t y_dn_sz_reg, uv_dn_sz_reg;
|
||
|
+
|
||
|
+ if (!list_index) {
|
||
|
+ y_dn_sz_reg = MISC1_Y_RX_LIST0_CUR_BYTE_CNT;
|
||
|
+ uv_dn_sz_reg = MISC1_UV_RX_LIST0_CUR_BYTE_CNT;
|
||
|
+ } else {
|
||
|
+ y_dn_sz_reg = MISC1_Y_RX_LIST1_CUR_BYTE_CNT;
|
||
|
+ uv_dn_sz_reg = MISC1_UV_RX_LIST1_CUR_BYTE_CNT;
|
||
|
+ }
|
||
|
+
|
||
|
+ *y_dw_dnsz = crystalhd_reg_rd(hw->adp, y_dn_sz_reg);
|
||
|
+ *uv_dw_dnsz = crystalhd_reg_rd(hw->adp, uv_dn_sz_reg);
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * This function should be called only after making sure that the two DMA
|
||
|
+ * lists are free. This function does not check if DMA's are active, before
|
||
|
+ * turning off the DMA.
|
||
|
+ */
|
||
|
+static void crystalhd_hw_finalize_pause(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ uint32_t dma_cntrl, aspm;
|
||
|
+
|
||
|
+ hw->stop_pending = 0;
|
||
|
+
|
||
|
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
|
||
|
+ if (dma_cntrl & DMA_START_BIT) {
|
||
|
+ dma_cntrl &= ~DMA_START_BIT;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
|
||
|
+ }
|
||
|
+
|
||
|
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
|
||
|
+ if (dma_cntrl & DMA_START_BIT) {
|
||
|
+ dma_cntrl &= ~DMA_START_BIT;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
|
||
|
+ }
|
||
|
+ hw->rx_list_post_index = 0;
|
||
|
+
|
||
|
+ aspm = crystalhd_reg_rd(hw->adp, PCIE_DLL_DATA_LINK_CONTROL);
|
||
|
+ aspm |= ASPM_L1_ENABLE;
|
||
|
+ /* NAREN BCMLOG(BCMLOG_INFO, "aspm on\n"); */
|
||
|
+ crystalhd_reg_wr(hw->adp, PCIE_DLL_DATA_LINK_CONTROL, aspm);
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS crystalhd_rx_pkt_done(struct crystalhd_hw *hw, uint32_t list_index,
|
||
|
+ BC_STATUS comp_sts)
|
||
|
+{
|
||
|
+ crystalhd_rx_dma_pkt *rx_pkt = NULL;
|
||
|
+ uint32_t y_dw_dnsz, uv_dw_dnsz;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ if (!hw || list_index >= DMA_ENGINE_CNT) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ rx_pkt = crystalhd_dioq_find_and_fetch(hw->rx_actq,
|
||
|
+ hw->rx_pkt_tag_seed + list_index);
|
||
|
+ if (!rx_pkt) {
|
||
|
+ BCMLOG_ERR("Act-Q:PostIx:%x L0Sts:%x L1Sts:%x current L:%x tag:%x comp:%x\n",
|
||
|
+ hw->rx_list_post_index, hw->rx_list_sts[0],
|
||
|
+ hw->rx_list_sts[1], list_index,
|
||
|
+ hw->rx_pkt_tag_seed + list_index, comp_sts);
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (comp_sts == BC_STS_SUCCESS) {
|
||
|
+ crystalhd_get_dnsz(hw, list_index, &y_dw_dnsz, &uv_dw_dnsz);
|
||
|
+ rx_pkt->dio_req->uinfo.y_done_sz = y_dw_dnsz;
|
||
|
+ rx_pkt->flags = COMP_FLAG_DATA_VALID;
|
||
|
+ if (rx_pkt->uv_phy_addr)
|
||
|
+ rx_pkt->dio_req->uinfo.uv_done_sz = uv_dw_dnsz;
|
||
|
+ crystalhd_dioq_add(hw->rx_rdyq, rx_pkt, true,
|
||
|
+ hw->rx_pkt_tag_seed + list_index);
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Check if we can post this DIO again. */
|
||
|
+ return crystalhd_hw_post_cap_buff(hw, rx_pkt);
|
||
|
+}
|
||
|
+
|
||
|
+static bool crystalhd_rx_list0_handler(struct crystalhd_hw *hw, uint32_t int_sts,
|
||
|
+ uint32_t y_err_sts, uint32_t uv_err_sts)
|
||
|
+{
|
||
|
+ uint32_t tmp;
|
||
|
+ list_sts tmp_lsts;
|
||
|
+
|
||
|
+ if (!(y_err_sts & GET_Y0_ERR_MSK) && !(uv_err_sts & GET_UV0_ERR_MSK))
|
||
|
+ return false;
|
||
|
+
|
||
|
+ tmp_lsts = hw->rx_list_sts[0];
|
||
|
+
|
||
|
+ /* Y0 - DMA */
|
||
|
+ tmp = y_err_sts & GET_Y0_ERR_MSK;
|
||
|
+ if (int_sts & INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK)
|
||
|
+ hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
|
||
|
+
|
||
|
+ if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK) {
|
||
|
+ hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
|
||
|
+ tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK) {
|
||
|
+ hw->rx_list_sts[0] &= ~rx_y_mask;
|
||
|
+ hw->rx_list_sts[0] |= rx_y_error;
|
||
|
+ tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (tmp) {
|
||
|
+ hw->rx_list_sts[0] &= ~rx_y_mask;
|
||
|
+ hw->rx_list_sts[0] |= rx_y_error;
|
||
|
+ hw->rx_list_post_index = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* UV0 - DMA */
|
||
|
+ tmp = uv_err_sts & GET_UV0_ERR_MSK;
|
||
|
+ if (int_sts & INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK)
|
||
|
+ hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
|
||
|
+
|
||
|
+ if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK) {
|
||
|
+ hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
|
||
|
+ tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK) {
|
||
|
+ hw->rx_list_sts[0] &= ~rx_uv_mask;
|
||
|
+ hw->rx_list_sts[0] |= rx_uv_error;
|
||
|
+ tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (tmp) {
|
||
|
+ hw->rx_list_sts[0] &= ~rx_uv_mask;
|
||
|
+ hw->rx_list_sts[0] |= rx_uv_error;
|
||
|
+ hw->rx_list_post_index = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (y_err_sts & GET_Y0_ERR_MSK) {
|
||
|
+ tmp = y_err_sts & GET_Y0_ERR_MSK;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_Y_RX_ERROR_STATUS, tmp);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (uv_err_sts & GET_UV0_ERR_MSK) {
|
||
|
+ tmp = uv_err_sts & GET_UV0_ERR_MSK;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_UV_RX_ERROR_STATUS, tmp);
|
||
|
+ }
|
||
|
+
|
||
|
+ return (tmp_lsts != hw->rx_list_sts[0]);
|
||
|
+}
|
||
|
+
|
||
|
+static bool crystalhd_rx_list1_handler(struct crystalhd_hw *hw, uint32_t int_sts,
|
||
|
+ uint32_t y_err_sts, uint32_t uv_err_sts)
|
||
|
+{
|
||
|
+ uint32_t tmp;
|
||
|
+ list_sts tmp_lsts;
|
||
|
+
|
||
|
+ if (!(y_err_sts & GET_Y1_ERR_MSK) && !(uv_err_sts & GET_UV1_ERR_MSK))
|
||
|
+ return false;
|
||
|
+
|
||
|
+ tmp_lsts = hw->rx_list_sts[1];
|
||
|
+
|
||
|
+ /* Y1 - DMA */
|
||
|
+ tmp = y_err_sts & GET_Y1_ERR_MSK;
|
||
|
+ if (int_sts & INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK)
|
||
|
+ hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
|
||
|
+
|
||
|
+ if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK) {
|
||
|
+ hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
|
||
|
+ tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK) {
|
||
|
+ /* Add retry-support..*/
|
||
|
+ hw->rx_list_sts[1] &= ~rx_y_mask;
|
||
|
+ hw->rx_list_sts[1] |= rx_y_error;
|
||
|
+ tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (tmp) {
|
||
|
+ hw->rx_list_sts[1] &= ~rx_y_mask;
|
||
|
+ hw->rx_list_sts[1] |= rx_y_error;
|
||
|
+ hw->rx_list_post_index = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* UV1 - DMA */
|
||
|
+ tmp = uv_err_sts & GET_UV1_ERR_MSK;
|
||
|
+ if (int_sts & INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK) {
|
||
|
+ hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK) {
|
||
|
+ hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
|
||
|
+ tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK) {
|
||
|
+ /* Add retry-support*/
|
||
|
+ hw->rx_list_sts[1] &= ~rx_uv_mask;
|
||
|
+ hw->rx_list_sts[1] |= rx_uv_error;
|
||
|
+ tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (tmp) {
|
||
|
+ hw->rx_list_sts[1] &= ~rx_uv_mask;
|
||
|
+ hw->rx_list_sts[1] |= rx_uv_error;
|
||
|
+ hw->rx_list_post_index = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (y_err_sts & GET_Y1_ERR_MSK) {
|
||
|
+ tmp = y_err_sts & GET_Y1_ERR_MSK;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_Y_RX_ERROR_STATUS, tmp);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (uv_err_sts & GET_UV1_ERR_MSK) {
|
||
|
+ tmp = uv_err_sts & GET_UV1_ERR_MSK;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC1_UV_RX_ERROR_STATUS, tmp);
|
||
|
+ }
|
||
|
+
|
||
|
+ return (tmp_lsts != hw->rx_list_sts[1]);
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static void crystalhd_rx_isr(struct crystalhd_hw *hw, uint32_t intr_sts)
|
||
|
+{
|
||
|
+ unsigned long flags;
|
||
|
+ uint32_t i, list_avail = 0;
|
||
|
+ BC_STATUS comp_sts = BC_STS_NO_DATA;
|
||
|
+ uint32_t y_err_sts, uv_err_sts, y_dn_sz = 0, uv_dn_sz = 0;
|
||
|
+ bool ret = 0;
|
||
|
+
|
||
|
+ if (!hw) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!(intr_sts & GET_RX_INTR_MASK))
|
||
|
+ return;
|
||
|
+
|
||
|
+ y_err_sts = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_ERROR_STATUS);
|
||
|
+ uv_err_sts = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_ERROR_STATUS);
|
||
|
+
|
||
|
+ for (i = 0; i < DMA_ENGINE_CNT; i++) {
|
||
|
+ /* Update States..*/
|
||
|
+ spin_lock_irqsave(&hw->rx_lock, flags);
|
||
|
+ if (i == 0)
|
||
|
+ ret = crystalhd_rx_list0_handler(hw, intr_sts, y_err_sts, uv_err_sts);
|
||
|
+ else
|
||
|
+ ret = crystalhd_rx_list1_handler(hw, intr_sts, y_err_sts, uv_err_sts);
|
||
|
+ if (ret) {
|
||
|
+ switch (hw->rx_list_sts[i]) {
|
||
|
+ case sts_free:
|
||
|
+ comp_sts = BC_STS_SUCCESS;
|
||
|
+ list_avail = 1;
|
||
|
+ break;
|
||
|
+ case rx_y_error:
|
||
|
+ case rx_uv_error:
|
||
|
+ case rx_sts_error:
|
||
|
+ /* We got error on both or Y or uv. */
|
||
|
+ hw->stats.rx_errors++;
|
||
|
+ crystalhd_get_dnsz(hw, i, &y_dn_sz, &uv_dn_sz);
|
||
|
+ /* FIXME: jarod: this is where my mini pci-e card is tripping up */
|
||
|
+ BCMLOG(BCMLOG_DBG, "list_index:%x rx[%d] Y:%x "
|
||
|
+ "UV:%x Int:%x YDnSz:%x UVDnSz:%x\n",
|
||
|
+ i, hw->stats.rx_errors, y_err_sts,
|
||
|
+ uv_err_sts, intr_sts, y_dn_sz, uv_dn_sz);
|
||
|
+ hw->rx_list_sts[i] = sts_free;
|
||
|
+ comp_sts = BC_STS_ERROR;
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ /* Wait for completion..*/
|
||
|
+ comp_sts = BC_STS_NO_DATA;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ spin_unlock_irqrestore(&hw->rx_lock, flags);
|
||
|
+
|
||
|
+ /* handle completion...*/
|
||
|
+ if (comp_sts != BC_STS_NO_DATA) {
|
||
|
+ crystalhd_rx_pkt_done(hw, i, comp_sts);
|
||
|
+ comp_sts = BC_STS_NO_DATA;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (list_avail) {
|
||
|
+ if (hw->stop_pending) {
|
||
|
+ if ((hw->rx_list_sts[0] == sts_free) &&
|
||
|
+ (hw->rx_list_sts[1] == sts_free))
|
||
|
+ crystalhd_hw_finalize_pause(hw);
|
||
|
+ } else {
|
||
|
+ crystalhd_hw_start_capture(hw);
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS crystalhd_fw_cmd_post_proc(struct crystalhd_hw *hw,
|
||
|
+ BC_FW_CMD *fw_cmd)
|
||
|
+{
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ DecRspChannelStartVideo *st_rsp = NULL;
|
||
|
+
|
||
|
+ switch (fw_cmd->cmd[0]) {
|
||
|
+ case eCMD_C011_DEC_CHAN_START_VIDEO:
|
||
|
+ st_rsp = (DecRspChannelStartVideo *)fw_cmd->rsp;
|
||
|
+ hw->pib_del_Q_addr = st_rsp->picInfoDeliveryQ;
|
||
|
+ hw->pib_rel_Q_addr = st_rsp->picInfoReleaseQ;
|
||
|
+ BCMLOG(BCMLOG_DBG, "DelQAddr:%x RelQAddr:%x\n",
|
||
|
+ hw->pib_del_Q_addr, hw->pib_rel_Q_addr);
|
||
|
+ break;
|
||
|
+ case eCMD_C011_INIT:
|
||
|
+ if (!(crystalhd_load_firmware_config(hw->adp))) {
|
||
|
+ BCMLOG_ERR("Invalid Params.\n");
|
||
|
+ sts = BC_STS_FW_AUTH_FAILED;
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+static BC_STATUS crystalhd_put_ddr2sleep(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ uint32_t reg;
|
||
|
+ link_misc_perst_decoder_ctrl rst_cntrl_reg;
|
||
|
+
|
||
|
+ /* Pulse reset pin of 7412 (MISC_PERST_DECODER_CTRL) */
|
||
|
+ rst_cntrl_reg.whole_reg = crystalhd_reg_rd(hw->adp, MISC_PERST_DECODER_CTRL);
|
||
|
+
|
||
|
+ rst_cntrl_reg.bcm_7412_rst = 1;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC_PERST_DECODER_CTRL, rst_cntrl_reg.whole_reg);
|
||
|
+ msleep_interruptible(50);
|
||
|
+
|
||
|
+ rst_cntrl_reg.bcm_7412_rst = 0;
|
||
|
+ crystalhd_reg_wr(hw->adp, MISC_PERST_DECODER_CTRL, rst_cntrl_reg.whole_reg);
|
||
|
+
|
||
|
+ /* Close all banks, put DDR in idle */
|
||
|
+ bc_dec_reg_wr(hw->adp, SDRAM_PRECHARGE, 0);
|
||
|
+
|
||
|
+ /* Set bit 25 (drop CKE pin of DDR) */
|
||
|
+ reg = bc_dec_reg_rd(hw->adp, SDRAM_PARAM);
|
||
|
+ reg |= 0x02000000;
|
||
|
+ bc_dec_reg_wr(hw->adp, SDRAM_PARAM, reg);
|
||
|
+
|
||
|
+ /* Reset the audio block */
|
||
|
+ bc_dec_reg_wr(hw->adp, AUD_DSP_MISC_SOFT_RESET, 0x1);
|
||
|
+
|
||
|
+ /* Power down Raptor PLL */
|
||
|
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllCCtl);
|
||
|
+ reg |= 0x00008000;
|
||
|
+ bc_dec_reg_wr(hw->adp, DecHt_PllCCtl, reg);
|
||
|
+
|
||
|
+ /* Power down all Audio PLL */
|
||
|
+ bc_dec_reg_wr(hw->adp, AIO_MISC_PLL_RESET, 0x1);
|
||
|
+
|
||
|
+ /* Power down video clock (75MHz) */
|
||
|
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllECtl);
|
||
|
+ reg |= 0x00008000;
|
||
|
+ bc_dec_reg_wr(hw->adp, DecHt_PllECtl, reg);
|
||
|
+
|
||
|
+ /* Power down video clock (75MHz) */
|
||
|
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllDCtl);
|
||
|
+ reg |= 0x00008000;
|
||
|
+ bc_dec_reg_wr(hw->adp, DecHt_PllDCtl, reg);
|
||
|
+
|
||
|
+ /* Power down core clock (200MHz) */
|
||
|
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
|
||
|
+ reg |= 0x00008000;
|
||
|
+ bc_dec_reg_wr(hw->adp, DecHt_PllACtl, reg);
|
||
|
+
|
||
|
+ /* Power down core clock (200MHz) */
|
||
|
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllBCtl);
|
||
|
+ reg |= 0x00008000;
|
||
|
+ bc_dec_reg_wr(hw->adp, DecHt_PllBCtl, reg);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/************************************************
|
||
|
+**
|
||
|
+*************************************************/
|
||
|
+
|
||
|
+BC_STATUS crystalhd_download_fw(struct crystalhd_adp *adp, void *buffer, uint32_t sz)
|
||
|
+{
|
||
|
+ uint32_t reg_data, cnt, *temp_buff;
|
||
|
+ uint32_t fw_sig_len = 36;
|
||
|
+ uint32_t dram_offset = BC_FWIMG_ST_ADDR, sig_reg;
|
||
|
+
|
||
|
+ BCMLOG_ENTER;
|
||
|
+
|
||
|
+ if (!adp || !buffer || !sz) {
|
||
|
+ BCMLOG_ERR("Invalid Params.\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ reg_data = crystalhd_reg_rd(adp, OTP_CMD);
|
||
|
+ if (!(reg_data & 0x02)) {
|
||
|
+ BCMLOG_ERR("Invalid hw config.. otp not programmed\n");
|
||
|
+ return BC_STS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ reg_data = 0;
|
||
|
+ crystalhd_reg_wr(adp, DCI_CMD, 0);
|
||
|
+ reg_data |= BC_BIT(0);
|
||
|
+ crystalhd_reg_wr(adp, DCI_CMD, reg_data);
|
||
|
+
|
||
|
+ reg_data = 0;
|
||
|
+ cnt = 1000;
|
||
|
+ msleep_interruptible(10);
|
||
|
+
|
||
|
+ while (reg_data != BC_BIT(4)) {
|
||
|
+ reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
|
||
|
+ reg_data &= BC_BIT(4);
|
||
|
+ if (--cnt == 0) {
|
||
|
+ BCMLOG_ERR("Firmware Download RDY Timeout.\n");
|
||
|
+ return BC_STS_TIMEOUT;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ msleep_interruptible(10);
|
||
|
+ /* Load the FW to the FW_ADDR field in the DCI_FIRMWARE_ADDR */
|
||
|
+ crystalhd_reg_wr(adp, DCI_FIRMWARE_ADDR, dram_offset);
|
||
|
+ temp_buff = (uint32_t *)buffer;
|
||
|
+ for (cnt = 0; cnt < (sz - fw_sig_len); cnt += 4) {
|
||
|
+ crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (dram_offset >> 19));
|
||
|
+ crystalhd_reg_wr(adp, DCI_FIRMWARE_DATA, *temp_buff);
|
||
|
+ dram_offset += 4;
|
||
|
+ temp_buff++;
|
||
|
+ }
|
||
|
+ msleep_interruptible(10);
|
||
|
+
|
||
|
+ temp_buff++;
|
||
|
+
|
||
|
+ sig_reg = (uint32_t)DCI_SIGNATURE_DATA_7;
|
||
|
+ for (cnt = 0; cnt < 8; cnt++) {
|
||
|
+ uint32_t swapped_data = *temp_buff;
|
||
|
+ swapped_data = bswap_32_1(swapped_data);
|
||
|
+ crystalhd_reg_wr(adp, sig_reg, swapped_data);
|
||
|
+ sig_reg -= 4;
|
||
|
+ temp_buff++;
|
||
|
+ }
|
||
|
+ msleep_interruptible(10);
|
||
|
+
|
||
|
+ reg_data = 0;
|
||
|
+ reg_data |= BC_BIT(1);
|
||
|
+ crystalhd_reg_wr(adp, DCI_CMD, reg_data);
|
||
|
+ msleep_interruptible(10);
|
||
|
+
|
||
|
+ reg_data = 0;
|
||
|
+ reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
|
||
|
+
|
||
|
+ if ((reg_data & BC_BIT(9)) == BC_BIT(9)) {
|
||
|
+ cnt = 1000;
|
||
|
+ while ((reg_data & BC_BIT(0)) != BC_BIT(0)) {
|
||
|
+ reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
|
||
|
+ reg_data &= BC_BIT(0);
|
||
|
+ if (!(--cnt))
|
||
|
+ break;
|
||
|
+ msleep_interruptible(10);
|
||
|
+ }
|
||
|
+ reg_data = 0;
|
||
|
+ reg_data = crystalhd_reg_rd(adp, DCI_CMD);
|
||
|
+ reg_data |= BC_BIT(4);
|
||
|
+ crystalhd_reg_wr(adp, DCI_CMD, reg_data);
|
||
|
+
|
||
|
+ } else {
|
||
|
+ BCMLOG_ERR("F/w Signature mismatch\n");
|
||
|
+ return BC_STS_FW_AUTH_FAILED;
|
||
|
+ }
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_INFO, "Firmware Downloaded Successfully\n");
|
||
|
+ return BC_STS_SUCCESS;;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_do_fw_cmd(struct crystalhd_hw *hw, BC_FW_CMD *fw_cmd)
|
||
|
+{
|
||
|
+ uint32_t cnt = 0, cmd_res_addr;
|
||
|
+ uint32_t *cmd_buff, *res_buff;
|
||
|
+ wait_queue_head_t fw_cmd_event;
|
||
|
+ int rc = 0;
|
||
|
+ BC_STATUS sts;
|
||
|
+
|
||
|
+ crystalhd_create_event(&fw_cmd_event);
|
||
|
+
|
||
|
+ BCMLOG_ENTER;
|
||
|
+
|
||
|
+ if (!hw || !fw_cmd) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ cmd_buff = fw_cmd->cmd;
|
||
|
+ res_buff = fw_cmd->rsp;
|
||
|
+
|
||
|
+ if (!cmd_buff || !res_buff) {
|
||
|
+ BCMLOG_ERR("Invalid Parameters for F/W Command \n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ hw->pwr_lock++;
|
||
|
+
|
||
|
+ hw->fwcmd_evt_sts = 0;
|
||
|
+ hw->pfw_cmd_event = &fw_cmd_event;
|
||
|
+
|
||
|
+ /*Write the command to the memory*/
|
||
|
+ crystalhd_mem_wr(hw->adp, TS_Host2CpuSnd, FW_CMD_BUFF_SZ, cmd_buff);
|
||
|
+
|
||
|
+ /*Memory Read for memory arbitrator flush*/
|
||
|
+ crystalhd_mem_rd(hw->adp, TS_Host2CpuSnd, 1, &cnt);
|
||
|
+
|
||
|
+ /* Write the command address to mailbox */
|
||
|
+ bc_dec_reg_wr(hw->adp, Hst2CpuMbx1, TS_Host2CpuSnd);
|
||
|
+ msleep_interruptible(50);
|
||
|
+
|
||
|
+ crystalhd_wait_on_event(&fw_cmd_event, hw->fwcmd_evt_sts, 20000, rc, 0);
|
||
|
+
|
||
|
+ if (!rc) {
|
||
|
+ sts = BC_STS_SUCCESS;
|
||
|
+ } else if (rc == -EBUSY) {
|
||
|
+ BCMLOG_ERR("Firmware command T/O\n");
|
||
|
+ sts = BC_STS_TIMEOUT;
|
||
|
+ } else if (rc == -EINTR) {
|
||
|
+ BCMLOG(BCMLOG_DBG, "FwCmd Wait Signal int.\n");
|
||
|
+ sts = BC_STS_IO_USER_ABORT;
|
||
|
+ } else {
|
||
|
+ BCMLOG_ERR("FwCmd IO Error.\n");
|
||
|
+ sts = BC_STS_IO_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("FwCmd Failed.\n");
|
||
|
+ hw->pwr_lock--;
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*Get the Responce Address*/
|
||
|
+ cmd_res_addr = bc_dec_reg_rd(hw->adp, Cpu2HstMbx1);
|
||
|
+
|
||
|
+ /*Read the Response*/
|
||
|
+ crystalhd_mem_rd(hw->adp, cmd_res_addr, FW_CMD_BUFF_SZ, res_buff);
|
||
|
+
|
||
|
+ hw->pwr_lock--;
|
||
|
+
|
||
|
+ if (res_buff[2] != C011_RET_SUCCESS) {
|
||
|
+ BCMLOG_ERR("res_buff[2] != C011_RET_SUCCESS\n");
|
||
|
+ return BC_STS_FW_CMD_ERR;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_fw_cmd_post_proc(hw, fw_cmd);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ BCMLOG_ERR("crystalhd_fw_cmd_post_proc Failed.\n");
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ uint32_t intr_sts = 0;
|
||
|
+ uint32_t deco_intr = 0;
|
||
|
+ bool rc = 0;
|
||
|
+
|
||
|
+ if (!adp || !hw->dev_started)
|
||
|
+ return rc;
|
||
|
+
|
||
|
+ hw->stats.num_interrupts++;
|
||
|
+ hw->pwr_lock++;
|
||
|
+
|
||
|
+ deco_intr = bc_dec_reg_rd(adp, Stream2Host_Intr_Sts);
|
||
|
+ intr_sts = crystalhd_reg_rd(adp, INTR_INTR_STATUS);
|
||
|
+
|
||
|
+ if (intr_sts) {
|
||
|
+ /* let system know we processed interrupt..*/
|
||
|
+ rc = 1;
|
||
|
+ hw->stats.dev_interrupts++;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (deco_intr && (deco_intr != 0xdeaddead)) {
|
||
|
+
|
||
|
+ if (deco_intr & 0x80000000) {
|
||
|
+ /*Set the Event and the status flag*/
|
||
|
+ if (hw->pfw_cmd_event) {
|
||
|
+ hw->fwcmd_evt_sts = 1;
|
||
|
+ crystalhd_set_event(hw->pfw_cmd_event);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (deco_intr & BC_BIT(1))
|
||
|
+ crystalhd_hw_proc_pib(hw);
|
||
|
+
|
||
|
+ bc_dec_reg_wr(adp, Stream2Host_Intr_Sts, deco_intr);
|
||
|
+ /* FIXME: jarod: No udelay? might this be the real reason mini pci-e cards were stalling out? */
|
||
|
+ bc_dec_reg_wr(adp, Stream2Host_Intr_Sts, 0);
|
||
|
+ rc = 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Rx interrupts */
|
||
|
+ crystalhd_rx_isr(hw, intr_sts);
|
||
|
+
|
||
|
+ /* Tx interrupts*/
|
||
|
+ crystalhd_tx_isr(hw, intr_sts);
|
||
|
+
|
||
|
+ /* Clear interrupts */
|
||
|
+ if (rc) {
|
||
|
+ if (intr_sts)
|
||
|
+ crystalhd_reg_wr(adp, INTR_INTR_CLR_REG, intr_sts);
|
||
|
+
|
||
|
+ crystalhd_reg_wr(adp, INTR_EOI_CTRL, 1);
|
||
|
+ }
|
||
|
+
|
||
|
+ hw->pwr_lock--;
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_open(struct crystalhd_hw *hw, struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ if (!hw || !adp) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (hw->dev_started)
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ memset(hw, 0, sizeof(struct crystalhd_hw));
|
||
|
+
|
||
|
+ hw->adp = adp;
|
||
|
+ spin_lock_init(&hw->lock);
|
||
|
+ spin_lock_init(&hw->rx_lock);
|
||
|
+ /* FIXME: jarod: what are these magic numbers?!? */
|
||
|
+ hw->tx_ioq_tag_seed = 0x70023070;
|
||
|
+ hw->rx_pkt_tag_seed = 0x70029070;
|
||
|
+
|
||
|
+ hw->stop_pending = 0;
|
||
|
+ crystalhd_start_device(hw->adp);
|
||
|
+ hw->dev_started = true;
|
||
|
+
|
||
|
+ /* set initial core clock */
|
||
|
+ hw->core_clock_mhz = CLOCK_PRESET;
|
||
|
+ hw->prev_n = 0;
|
||
|
+ hw->pwr_lock = 0;
|
||
|
+ crystalhd_hw_set_core_clock(hw);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_close(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ if (!hw) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!hw->dev_started)
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ /* Stop and DDR sleep will happen in here */
|
||
|
+ crystalhd_hw_suspend(hw);
|
||
|
+ hw->dev_started = false;
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ unsigned int i;
|
||
|
+ void *mem;
|
||
|
+ size_t mem_len;
|
||
|
+ dma_addr_t phy_addr;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ crystalhd_rx_dma_pkt *rpkt;
|
||
|
+
|
||
|
+ if (!hw || !hw->adp) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_hw_create_ioqs(hw);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("Failed to create IOQs..\n");
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+
|
||
|
+ mem_len = BC_LINK_MAX_SGLS * sizeof(dma_descriptor);
|
||
|
+
|
||
|
+ for (i = 0; i < BC_TX_LIST_CNT; i++) {
|
||
|
+ mem = bc_kern_dma_alloc(hw->adp, mem_len, &phy_addr);
|
||
|
+ if (mem) {
|
||
|
+ memset(mem, 0, mem_len);
|
||
|
+ } else {
|
||
|
+ BCMLOG_ERR("Insufficient Memory For TX\n");
|
||
|
+ crystalhd_hw_free_dma_rings(hw);
|
||
|
+ return BC_STS_INSUFF_RES;
|
||
|
+ }
|
||
|
+ /* rx_pkt_pool -- static memory allocation */
|
||
|
+ hw->tx_pkt_pool[i].desc_mem.pdma_desc_start = mem;
|
||
|
+ hw->tx_pkt_pool[i].desc_mem.phy_addr = phy_addr;
|
||
|
+ hw->tx_pkt_pool[i].desc_mem.sz = BC_LINK_MAX_SGLS *
|
||
|
+ sizeof(dma_descriptor);
|
||
|
+ hw->tx_pkt_pool[i].list_tag = 0;
|
||
|
+
|
||
|
+ /* Add TX dma requests to Free Queue..*/
|
||
|
+ sts = crystalhd_dioq_add(hw->tx_freeq,
|
||
|
+ &hw->tx_pkt_pool[i], false, 0);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ crystalhd_hw_free_dma_rings(hw);
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ for (i = 0; i < BC_RX_LIST_CNT; i++) {
|
||
|
+ rpkt = kzalloc(sizeof(*rpkt), GFP_KERNEL);
|
||
|
+ if (!rpkt) {
|
||
|
+ BCMLOG_ERR("Insufficient Memory For RX\n");
|
||
|
+ crystalhd_hw_free_dma_rings(hw);
|
||
|
+ return BC_STS_INSUFF_RES;
|
||
|
+ }
|
||
|
+
|
||
|
+ mem = bc_kern_dma_alloc(hw->adp, mem_len, &phy_addr);
|
||
|
+ if (mem) {
|
||
|
+ memset(mem, 0, mem_len);
|
||
|
+ } else {
|
||
|
+ BCMLOG_ERR("Insufficient Memory For RX\n");
|
||
|
+ crystalhd_hw_free_dma_rings(hw);
|
||
|
+ return BC_STS_INSUFF_RES;
|
||
|
+ }
|
||
|
+ rpkt->desc_mem.pdma_desc_start = mem;
|
||
|
+ rpkt->desc_mem.phy_addr = phy_addr;
|
||
|
+ rpkt->desc_mem.sz = BC_LINK_MAX_SGLS * sizeof(dma_descriptor);
|
||
|
+ rpkt->pkt_tag = hw->rx_pkt_tag_seed + i;
|
||
|
+ crystalhd_hw_free_rx_pkt(hw, rpkt);
|
||
|
+ }
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_free_dma_rings(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ unsigned int i;
|
||
|
+ crystalhd_rx_dma_pkt *rpkt = NULL;
|
||
|
+
|
||
|
+ if (!hw || !hw->adp) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Delete all IOQs.. */
|
||
|
+ crystalhd_hw_delete_ioqs(hw);
|
||
|
+
|
||
|
+ for (i = 0; i < BC_TX_LIST_CNT; i++) {
|
||
|
+ if (hw->tx_pkt_pool[i].desc_mem.pdma_desc_start) {
|
||
|
+ bc_kern_dma_free(hw->adp,
|
||
|
+ hw->tx_pkt_pool[i].desc_mem.sz,
|
||
|
+ hw->tx_pkt_pool[i].desc_mem.pdma_desc_start,
|
||
|
+ hw->tx_pkt_pool[i].desc_mem.phy_addr);
|
||
|
+
|
||
|
+ hw->tx_pkt_pool[i].desc_mem.pdma_desc_start = NULL;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DBG, "Releasing RX Pkt pool\n");
|
||
|
+ do {
|
||
|
+ rpkt = crystalhd_hw_alloc_rx_pkt(hw);
|
||
|
+ if (!rpkt)
|
||
|
+ break;
|
||
|
+ bc_kern_dma_free(hw->adp, rpkt->desc_mem.sz,
|
||
|
+ rpkt->desc_mem.pdma_desc_start,
|
||
|
+ rpkt->desc_mem.phy_addr);
|
||
|
+ kfree(rpkt);
|
||
|
+ } while (rpkt);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_post_tx(struct crystalhd_hw *hw, crystalhd_dio_req *ioreq,
|
||
|
+ hw_comp_callback call_back,
|
||
|
+ wait_queue_head_t *cb_event, uint32_t *list_id,
|
||
|
+ uint8_t data_flags)
|
||
|
+{
|
||
|
+ tx_dma_pkt *tx_dma_packet = NULL;
|
||
|
+ uint32_t first_desc_u_addr, first_desc_l_addr;
|
||
|
+ uint32_t low_addr, high_addr;
|
||
|
+ addr_64 desc_addr;
|
||
|
+ BC_STATUS sts, add_sts;
|
||
|
+ uint32_t dummy_index = 0;
|
||
|
+ unsigned long flags;
|
||
|
+ bool rc;
|
||
|
+
|
||
|
+ if (!hw || !ioreq || !call_back || !cb_event || !list_id) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Since we hit code in busy condition very frequently,
|
||
|
+ * we will check the code in status first before
|
||
|
+ * checking the availability of free elem.
|
||
|
+ *
|
||
|
+ * This will avoid the Q fetch/add in normal condition.
|
||
|
+ */
|
||
|
+ rc = crystalhd_code_in_full(hw->adp, ioreq->uinfo.xfr_len,
|
||
|
+ false, data_flags);
|
||
|
+ if (rc) {
|
||
|
+ hw->stats.cin_busy++;
|
||
|
+ return BC_STS_BUSY;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Get a list from TxFreeQ */
|
||
|
+ tx_dma_packet = (tx_dma_pkt *)crystalhd_dioq_fetch(hw->tx_freeq);
|
||
|
+ if (!tx_dma_packet) {
|
||
|
+ BCMLOG_ERR("No empty elements..\n");
|
||
|
+ return BC_STS_ERR_USAGE;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_xlat_sgl_to_dma_desc(ioreq,
|
||
|
+ &tx_dma_packet->desc_mem,
|
||
|
+ &dummy_index);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ add_sts = crystalhd_dioq_add(hw->tx_freeq, tx_dma_packet,
|
||
|
+ false, 0);
|
||
|
+ if (add_sts != BC_STS_SUCCESS)
|
||
|
+ BCMLOG_ERR("double fault..\n");
|
||
|
+
|
||
|
+ return sts;
|
||
|
+ }
|
||
|
+
|
||
|
+ hw->pwr_lock++;
|
||
|
+
|
||
|
+ desc_addr.full_addr = tx_dma_packet->desc_mem.phy_addr;
|
||
|
+ low_addr = desc_addr.low_part;
|
||
|
+ high_addr = desc_addr.high_part;
|
||
|
+
|
||
|
+ tx_dma_packet->call_back = call_back;
|
||
|
+ tx_dma_packet->cb_event = cb_event;
|
||
|
+ tx_dma_packet->dio_req = ioreq;
|
||
|
+
|
||
|
+ spin_lock_irqsave(&hw->lock, flags);
|
||
|
+
|
||
|
+ if (hw->tx_list_post_index == 0) {
|
||
|
+ first_desc_u_addr = MISC1_TX_FIRST_DESC_U_ADDR_LIST0;
|
||
|
+ first_desc_l_addr = MISC1_TX_FIRST_DESC_L_ADDR_LIST0;
|
||
|
+ } else {
|
||
|
+ first_desc_u_addr = MISC1_TX_FIRST_DESC_U_ADDR_LIST1;
|
||
|
+ first_desc_l_addr = MISC1_TX_FIRST_DESC_L_ADDR_LIST1;
|
||
|
+ }
|
||
|
+
|
||
|
+ *list_id = tx_dma_packet->list_tag = hw->tx_ioq_tag_seed +
|
||
|
+ hw->tx_list_post_index;
|
||
|
+
|
||
|
+ hw->tx_list_post_index = (hw->tx_list_post_index + 1) % DMA_ENGINE_CNT;
|
||
|
+
|
||
|
+ spin_unlock_irqrestore(&hw->lock, flags);
|
||
|
+
|
||
|
+
|
||
|
+ /* Insert in Active Q..*/
|
||
|
+ crystalhd_dioq_add(hw->tx_actq, tx_dma_packet, false,
|
||
|
+ tx_dma_packet->list_tag);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Interrupt will come as soon as you write
|
||
|
+ * the valid bit. So be ready for that. All
|
||
|
+ * the initialization should happen before that.
|
||
|
+ */
|
||
|
+ crystalhd_start_tx_dma_engine(hw);
|
||
|
+ crystalhd_reg_wr(hw->adp, first_desc_u_addr, desc_addr.high_part);
|
||
|
+
|
||
|
+ crystalhd_reg_wr(hw->adp, first_desc_l_addr, desc_addr.low_part | 0x01);
|
||
|
+ /* Be sure we set the valid bit ^^^^ */
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * This is a force cancel and we are racing with ISR.
|
||
|
+ *
|
||
|
+ * Will try to remove the req from ActQ before ISR gets it.
|
||
|
+ * If ISR gets it first then the completion happens in the
|
||
|
+ * normal path and we will return _STS_NO_DATA from here.
|
||
|
+ *
|
||
|
+ * FIX_ME: Not Tested the actual condition..
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_hw_cancel_tx(struct crystalhd_hw *hw, uint32_t list_id)
|
||
|
+{
|
||
|
+ if (!hw || !list_id) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_stop_tx_dma_engine(hw);
|
||
|
+ crystalhd_hw_tx_req_complete(hw, list_id, BC_STS_IO_USER_ABORT);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_add_cap_buffer(struct crystalhd_hw *hw,
|
||
|
+ crystalhd_dio_req *ioreq, bool en_post)
|
||
|
+{
|
||
|
+ crystalhd_rx_dma_pkt *rpkt;
|
||
|
+ uint32_t tag, uv_desc_ix = 0;
|
||
|
+ BC_STATUS sts;
|
||
|
+
|
||
|
+ if (!hw || !ioreq) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ rpkt = crystalhd_hw_alloc_rx_pkt(hw);
|
||
|
+ if (!rpkt) {
|
||
|
+ BCMLOG_ERR("Insufficient resources\n");
|
||
|
+ return BC_STS_INSUFF_RES;
|
||
|
+ }
|
||
|
+
|
||
|
+ rpkt->dio_req = ioreq;
|
||
|
+ tag = rpkt->pkt_tag;
|
||
|
+
|
||
|
+ sts = crystalhd_xlat_sgl_to_dma_desc(ioreq, &rpkt->desc_mem, &uv_desc_ix);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ return sts;
|
||
|
+
|
||
|
+ rpkt->uv_phy_addr = 0;
|
||
|
+
|
||
|
+ /* Store the address of UV in the rx packet for post*/
|
||
|
+ if (uv_desc_ix)
|
||
|
+ rpkt->uv_phy_addr = rpkt->desc_mem.phy_addr +
|
||
|
+ (sizeof(dma_descriptor) * (uv_desc_ix + 1));
|
||
|
+
|
||
|
+ if (en_post)
|
||
|
+ sts = crystalhd_hw_post_cap_buff(hw, rpkt);
|
||
|
+ else
|
||
|
+ sts = crystalhd_dioq_add(hw->rx_freeq, rpkt, false, tag);
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_get_cap_buffer(struct crystalhd_hw *hw,
|
||
|
+ BC_PIC_INFO_BLOCK *pib,
|
||
|
+ crystalhd_dio_req **ioreq)
|
||
|
+{
|
||
|
+ crystalhd_rx_dma_pkt *rpkt;
|
||
|
+ uint32_t timeout = BC_PROC_OUTPUT_TIMEOUT / 1000;
|
||
|
+ uint32_t sig_pending = 0;
|
||
|
+
|
||
|
+
|
||
|
+ if (!hw || !ioreq || !pib) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ rpkt = crystalhd_dioq_fetch_wait(hw->rx_rdyq, timeout, &sig_pending);
|
||
|
+ if (!rpkt) {
|
||
|
+ if (sig_pending) {
|
||
|
+ BCMLOG(BCMLOG_INFO, "wait on frame time out %d\n", sig_pending);
|
||
|
+ return BC_STS_IO_USER_ABORT;
|
||
|
+ } else {
|
||
|
+ return BC_STS_TIMEOUT;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ rpkt->dio_req->uinfo.comp_flags = rpkt->flags;
|
||
|
+
|
||
|
+ if (rpkt->flags & COMP_FLAG_PIB_VALID)
|
||
|
+ memcpy(pib, &rpkt->pib, sizeof(*pib));
|
||
|
+
|
||
|
+ *ioreq = rpkt->dio_req;
|
||
|
+
|
||
|
+ crystalhd_hw_free_rx_pkt(hw, rpkt);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_start_capture(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ crystalhd_rx_dma_pkt *rx_pkt;
|
||
|
+ BC_STATUS sts;
|
||
|
+ uint32_t i;
|
||
|
+
|
||
|
+ if (!hw) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* This is start of capture.. Post to both the lists.. */
|
||
|
+ for (i = 0; i < DMA_ENGINE_CNT; i++) {
|
||
|
+ rx_pkt = crystalhd_dioq_fetch(hw->rx_freeq);
|
||
|
+ if (!rx_pkt)
|
||
|
+ return BC_STS_NO_DATA;
|
||
|
+ sts = crystalhd_hw_post_cap_buff(hw, rx_pkt);
|
||
|
+ if (BC_STS_SUCCESS != sts)
|
||
|
+ break;
|
||
|
+
|
||
|
+ }
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_stop_capture(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ void *temp = NULL;
|
||
|
+
|
||
|
+ if (!hw) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_stop_rx_dma_engine(hw);
|
||
|
+
|
||
|
+ do {
|
||
|
+ temp = crystalhd_dioq_fetch(hw->rx_freeq);
|
||
|
+ if (temp)
|
||
|
+ crystalhd_rx_pkt_rel_call_back(hw, temp);
|
||
|
+ } while (temp);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_pause(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ hw->stats.pause_cnt++;
|
||
|
+ hw->stop_pending = 1;
|
||
|
+
|
||
|
+ if ((hw->rx_list_sts[0] == sts_free) &&
|
||
|
+ (hw->rx_list_sts[1] == sts_free))
|
||
|
+ crystalhd_hw_finalize_pause(hw);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_unpause(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ BC_STATUS sts;
|
||
|
+ uint32_t aspm;
|
||
|
+
|
||
|
+ hw->stop_pending = 0;
|
||
|
+
|
||
|
+ aspm = crystalhd_reg_rd(hw->adp, PCIE_DLL_DATA_LINK_CONTROL);
|
||
|
+ aspm &= ~ASPM_L1_ENABLE;
|
||
|
+/* NAREN BCMLOG(BCMLOG_INFO, "aspm off\n"); */
|
||
|
+ crystalhd_reg_wr(hw->adp, PCIE_DLL_DATA_LINK_CONTROL, aspm);
|
||
|
+
|
||
|
+ sts = crystalhd_hw_start_capture(hw);
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_suspend(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ BC_STATUS sts;
|
||
|
+
|
||
|
+ if (!hw) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_put_ddr2sleep(hw);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("Failed to Put DDR To Sleep!!\n");
|
||
|
+ return BC_STS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!crystalhd_stop_device(hw->adp)) {
|
||
|
+ BCMLOG_ERR("Failed to Stop Device!!\n");
|
||
|
+ return BC_STS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+void crystalhd_hw_stats(struct crystalhd_hw *hw, struct crystalhd_hw_stats *stats)
|
||
|
+{
|
||
|
+ if (!hw) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* if called w/NULL stats, its a req to zero out the stats */
|
||
|
+ if (!stats) {
|
||
|
+ memset(&hw->stats, 0, sizeof(hw->stats));
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ hw->stats.freeq_count = crystalhd_dioq_count(hw->rx_freeq);
|
||
|
+ hw->stats.rdyq_count = crystalhd_dioq_count(hw->rx_rdyq);
|
||
|
+ memcpy(stats, &hw->stats, sizeof(*stats));
|
||
|
+}
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_set_core_clock(struct crystalhd_hw *hw)
|
||
|
+{
|
||
|
+ uint32_t reg, n, i;
|
||
|
+ uint32_t vco_mg, refresh_reg;
|
||
|
+
|
||
|
+ if (!hw) {
|
||
|
+ BCMLOG_ERR("Invalid Arguments\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* FIXME: jarod: wha? */
|
||
|
+ /*n = (hw->core_clock_mhz * 3) / 20 + 1; */
|
||
|
+ n = hw->core_clock_mhz/5;
|
||
|
+
|
||
|
+ if (n == hw->prev_n)
|
||
|
+ return BC_STS_CLK_NOCHG;
|
||
|
+
|
||
|
+ if (hw->pwr_lock > 0) {
|
||
|
+ /* BCMLOG(BCMLOG_INFO,"pwr_lock is %u\n", hw->pwr_lock) */
|
||
|
+ return BC_STS_CLK_NOCHG;
|
||
|
+ }
|
||
|
+
|
||
|
+ i = n * 27;
|
||
|
+ if (i < 560)
|
||
|
+ vco_mg = 0;
|
||
|
+ else if (i < 900)
|
||
|
+ vco_mg = 1;
|
||
|
+ else if (i < 1030)
|
||
|
+ vco_mg = 2;
|
||
|
+ else
|
||
|
+ vco_mg = 3;
|
||
|
+
|
||
|
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
|
||
|
+
|
||
|
+ reg &= 0xFFFFCFC0;
|
||
|
+ reg |= n;
|
||
|
+ reg |= vco_mg << 12;
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_INFO, "clock is moving to %d with n %d with vco_mg %d\n",
|
||
|
+ hw->core_clock_mhz, n, vco_mg);
|
||
|
+
|
||
|
+ /* Change the DRAM refresh rate to accomodate the new frequency */
|
||
|
+ /* refresh reg = ((refresh_rate * clock_rate)/16) - 1; rounding up*/
|
||
|
+ refresh_reg = (7 * hw->core_clock_mhz / 16);
|
||
|
+ bc_dec_reg_wr(hw->adp, SDRAM_REF_PARAM, ((1 << 12) | refresh_reg));
|
||
|
+
|
||
|
+ bc_dec_reg_wr(hw->adp, DecHt_PllACtl, reg);
|
||
|
+
|
||
|
+ i = 0;
|
||
|
+
|
||
|
+ for (i = 0; i < 10; i++) {
|
||
|
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
|
||
|
+
|
||
|
+ if (reg & 0x00020000) {
|
||
|
+ hw->prev_n = n;
|
||
|
+ /* FIXME: jarod: outputting a random "C" is... confusing... */
|
||
|
+ BCMLOG(BCMLOG_INFO, "C");
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+ } else {
|
||
|
+ msleep_interruptible(10);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ BCMLOG(BCMLOG_INFO, "clk change failed\n");
|
||
|
+ return BC_STS_CLK_NOCHG;
|
||
|
+}
|
||
|
diff --git a/drivers/staging/crystalhd/crystalhd_hw.h b/drivers/staging/crystalhd/crystalhd_hw.h
|
||
|
new file mode 100644
|
||
|
index 0000000..1c6318e
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/crystalhd_hw.h
|
||
|
@@ -0,0 +1,398 @@
|
||
|
+/***************************************************************************
|
||
|
+ * Copyright (c) 2005-2009, Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: crystalhd_hw . h
|
||
|
+ *
|
||
|
+ * Description:
|
||
|
+ * BCM70012 Linux driver hardware layer.
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ **********************************************************************
|
||
|
+ * This file is part of the crystalhd device driver.
|
||
|
+ *
|
||
|
+ * This driver is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, version 2 of the License.
|
||
|
+ *
|
||
|
+ * This driver is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this driver. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ **********************************************************************/
|
||
|
+
|
||
|
+#ifndef _CRYSTALHD_HW_H_
|
||
|
+#define _CRYSTALHD_HW_H_
|
||
|
+
|
||
|
+#include "crystalhd_misc.h"
|
||
|
+#include "crystalhd_fw_if.h"
|
||
|
+
|
||
|
+/* HW constants..*/
|
||
|
+#define DMA_ENGINE_CNT 2
|
||
|
+#define MAX_PIB_Q_DEPTH 64
|
||
|
+#define MIN_PIB_Q_DEPTH 2
|
||
|
+#define WR_POINTER_OFF 4
|
||
|
+
|
||
|
+#define ASPM_L1_ENABLE (BC_BIT(27))
|
||
|
+
|
||
|
+/*************************************************
|
||
|
+ 7412 Decoder Registers.
|
||
|
+**************************************************/
|
||
|
+#define FW_CMD_BUFF_SZ 64
|
||
|
+#define TS_Host2CpuSnd 0x00000100
|
||
|
+#define Hst2CpuMbx1 0x00100F00
|
||
|
+#define Cpu2HstMbx1 0x00100F04
|
||
|
+#define MbxStat1 0x00100F08
|
||
|
+#define Stream2Host_Intr_Sts 0x00100F24
|
||
|
+#define C011_RET_SUCCESS 0x0 /* Reutrn status of firmware command. */
|
||
|
+
|
||
|
+/* TS input status register */
|
||
|
+#define TS_StreamAFIFOStatus 0x0010044C
|
||
|
+#define TS_StreamBFIFOStatus 0x0010084C
|
||
|
+
|
||
|
+/*UART Selection definitions*/
|
||
|
+#define UartSelectA 0x00100300
|
||
|
+#define UartSelectB 0x00100304
|
||
|
+
|
||
|
+#define BSVS_UART_DEC_NONE 0x00
|
||
|
+#define BSVS_UART_DEC_OUTER 0x01
|
||
|
+#define BSVS_UART_DEC_INNER 0x02
|
||
|
+#define BSVS_UART_STREAM 0x03
|
||
|
+
|
||
|
+/* Code-In fifo */
|
||
|
+#define REG_DecCA_RegCinCTL 0xa00
|
||
|
+#define REG_DecCA_RegCinBase 0xa0c
|
||
|
+#define REG_DecCA_RegCinEnd 0xa10
|
||
|
+#define REG_DecCA_RegCinWrPtr 0xa04
|
||
|
+#define REG_DecCA_RegCinRdPtr 0xa08
|
||
|
+
|
||
|
+#define REG_Dec_TsUser0Base 0x100864
|
||
|
+#define REG_Dec_TsUser0Rdptr 0x100868
|
||
|
+#define REG_Dec_TsUser0Wrptr 0x10086C
|
||
|
+#define REG_Dec_TsUser0End 0x100874
|
||
|
+
|
||
|
+/* ASF Case ...*/
|
||
|
+#define REG_Dec_TsAudCDB2Base 0x10036c
|
||
|
+#define REG_Dec_TsAudCDB2Rdptr 0x100378
|
||
|
+#define REG_Dec_TsAudCDB2Wrptr 0x100374
|
||
|
+#define REG_Dec_TsAudCDB2End 0x100370
|
||
|
+
|
||
|
+/* DRAM bringup Registers */
|
||
|
+#define SDRAM_PARAM 0x00040804
|
||
|
+#define SDRAM_PRECHARGE 0x000408B0
|
||
|
+#define SDRAM_EXT_MODE 0x000408A4
|
||
|
+#define SDRAM_MODE 0x000408A0
|
||
|
+#define SDRAM_REFRESH 0x00040890
|
||
|
+#define SDRAM_REF_PARAM 0x00040808
|
||
|
+
|
||
|
+#define DecHt_PllACtl 0x34000C
|
||
|
+#define DecHt_PllBCtl 0x340010
|
||
|
+#define DecHt_PllCCtl 0x340014
|
||
|
+#define DecHt_PllDCtl 0x340034
|
||
|
+#define DecHt_PllECtl 0x340038
|
||
|
+#define AUD_DSP_MISC_SOFT_RESET 0x00240104
|
||
|
+#define AIO_MISC_PLL_RESET 0x0026000C
|
||
|
+#define PCIE_CLK_REQ_REG 0xDC
|
||
|
+#define PCI_CLK_REQ_ENABLE (BC_BIT(8))
|
||
|
+
|
||
|
+/*************************************************
|
||
|
+ F/W Copy engine definitions..
|
||
|
+**************************************************/
|
||
|
+#define BC_FWIMG_ST_ADDR 0x00000000
|
||
|
+/* FIXME: jarod: there's a kernel function that'll do this for us... */
|
||
|
+#define rotr32_1(x, n) (((x) >> n) | ((x) << (32 - n)))
|
||
|
+#define bswap_32_1(x) ((rotr32_1((x), 24) & 0x00ff00ff) | (rotr32_1((x), 8) & 0xff00ff00))
|
||
|
+
|
||
|
+#define DecHt_HostSwReset 0x340000
|
||
|
+#define BC_DRAM_FW_CFG_ADDR 0x001c2000
|
||
|
+
|
||
|
+typedef union _addr_64_ {
|
||
|
+ struct {
|
||
|
+ uint32_t low_part;
|
||
|
+ uint32_t high_part;
|
||
|
+ };
|
||
|
+
|
||
|
+ uint64_t full_addr;
|
||
|
+
|
||
|
+} addr_64;
|
||
|
+
|
||
|
+typedef union _intr_mask_reg_ {
|
||
|
+ struct {
|
||
|
+ uint32_t mask_tx_done:1;
|
||
|
+ uint32_t mask_tx_err:1;
|
||
|
+ uint32_t mask_rx_done:1;
|
||
|
+ uint32_t mask_rx_err:1;
|
||
|
+ uint32_t mask_pcie_err:1;
|
||
|
+ uint32_t mask_pcie_rbusmast_err:1;
|
||
|
+ uint32_t mask_pcie_rgr_bridge:1;
|
||
|
+ uint32_t reserved:25;
|
||
|
+ };
|
||
|
+
|
||
|
+ uint32_t whole_reg;
|
||
|
+
|
||
|
+} intr_mask_reg;
|
||
|
+
|
||
|
+typedef union _link_misc_perst_deco_ctrl_ {
|
||
|
+ struct {
|
||
|
+ uint32_t bcm7412_rst:1; /* 1 -> BCM7412 is held in reset. Reset value 1.*/
|
||
|
+ uint32_t reserved0:3; /* Reserved.No Effect*/
|
||
|
+ uint32_t stop_bcm_7412_clk:1; /* 1 ->Stops branch of 27MHz clk used to clk BCM7412*/
|
||
|
+ uint32_t reserved1:27; /* Reseved. No Effect*/
|
||
|
+ };
|
||
|
+
|
||
|
+ uint32_t whole_reg;
|
||
|
+
|
||
|
+} link_misc_perst_deco_ctrl;
|
||
|
+
|
||
|
+typedef union _link_misc_perst_clk_ctrl_ {
|
||
|
+ struct {
|
||
|
+ uint32_t sel_alt_clk:1; /* When set, selects a 6.75MHz clock as the source of core_clk */
|
||
|
+ uint32_t stop_core_clk:1; /* When set, stops the branch of core_clk that is not needed for low power operation */
|
||
|
+ uint32_t pll_pwr_dn:1; /* When set, powers down the main PLL. The alternate clock bit should be set
|
||
|
+ to select an alternate clock before setting this bit.*/
|
||
|
+ uint32_t reserved0:5; /* Reserved */
|
||
|
+ uint32_t pll_mult:8; /* This setting controls the multiplier for the PLL. */
|
||
|
+ uint32_t pll_div:4; /* This setting controls the divider for the PLL. */
|
||
|
+ uint32_t reserved1:12; /* Reserved */
|
||
|
+ };
|
||
|
+
|
||
|
+ uint32_t whole_reg;
|
||
|
+
|
||
|
+} link_misc_perst_clk_ctrl;
|
||
|
+
|
||
|
+
|
||
|
+typedef union _link_misc_perst_decoder_ctrl_ {
|
||
|
+ struct {
|
||
|
+ uint32_t bcm_7412_rst:1; /* 1 -> BCM7412 is held in reset. Reset value 1.*/
|
||
|
+ uint32_t res0:3; /* Reserved.No Effect*/
|
||
|
+ uint32_t stop_7412_clk:1; /* 1 ->Stops branch of 27MHz clk used to clk BCM7412*/
|
||
|
+ uint32_t res1:27; /* Reseved. No Effect */
|
||
|
+ };
|
||
|
+
|
||
|
+ uint32_t whole_reg;
|
||
|
+
|
||
|
+} link_misc_perst_decoder_ctrl;
|
||
|
+
|
||
|
+
|
||
|
+typedef union _desc_low_addr_reg_ {
|
||
|
+ struct {
|
||
|
+ uint32_t list_valid:1;
|
||
|
+ uint32_t reserved:4;
|
||
|
+ uint32_t low_addr:27;
|
||
|
+ };
|
||
|
+
|
||
|
+ uint32_t whole_reg;
|
||
|
+
|
||
|
+} desc_low_addr_reg;
|
||
|
+
|
||
|
+typedef struct _dma_descriptor_ { /* 8 32-bit values */
|
||
|
+ /* 0th u32 */
|
||
|
+ uint32_t sdram_buff_addr:28; /* bits 0-27: SDRAM Address */
|
||
|
+ uint32_t res0:4; /* bits 28-31: Reserved */
|
||
|
+
|
||
|
+ /* 1st u32 */
|
||
|
+ uint32_t buff_addr_low; /* 1 buffer address low */
|
||
|
+ uint32_t buff_addr_high; /* 2 buffer address high */
|
||
|
+
|
||
|
+ /* 3rd u32 */
|
||
|
+ uint32_t res2:2; /* 0-1 - Reserved */
|
||
|
+ uint32_t xfer_size:23; /* 2-24 = Xfer size in words */
|
||
|
+ uint32_t res3:6; /* 25-30 reserved */
|
||
|
+ uint32_t intr_enable:1; /* 31 - Interrupt After this desc */
|
||
|
+
|
||
|
+ /* 4th u32 */
|
||
|
+ uint32_t endian_xlat_align:2; /* 0-1 Endian Translation */
|
||
|
+ uint32_t next_desc_cont:1; /* 2 - Next desc is in contig memory */
|
||
|
+ uint32_t res4:25; /* 3 - 27 Reserved bits */
|
||
|
+ uint32_t fill_bytes:2; /* 28-29 Bits Fill Bytes */
|
||
|
+ uint32_t dma_dir:1; /* 30 bit DMA Direction */
|
||
|
+ uint32_t last_rec_indicator:1; /* 31 bit Last Record Indicator */
|
||
|
+
|
||
|
+ /* 5th u32 */
|
||
|
+ uint32_t next_desc_addr_low; /* 32-bits Next Desc Addr lower */
|
||
|
+
|
||
|
+ /* 6th u32 */
|
||
|
+ uint32_t next_desc_addr_high; /* 32-bits Next Desc Addr Higher */
|
||
|
+
|
||
|
+ /* 7th u32 */
|
||
|
+ uint32_t res8; /* Last 32bits reserved */
|
||
|
+
|
||
|
+} dma_descriptor, *pdma_descriptor;
|
||
|
+
|
||
|
+/*
|
||
|
+ * We will allocate the memory in 4K pages
|
||
|
+ * the linked list will be a list of 32 byte descriptors.
|
||
|
+ * The virtual address will determine what should be freed.
|
||
|
+ */
|
||
|
+typedef struct _dma_desc_mem_ {
|
||
|
+ pdma_descriptor pdma_desc_start; /* 32-bytes for dma descriptor. should be first element */
|
||
|
+ dma_addr_t phy_addr; /* physical address of each DMA desc */
|
||
|
+ uint32_t sz;
|
||
|
+ struct _dma_desc_mem_ *Next; /* points to Next Descriptor in chain */
|
||
|
+
|
||
|
+} dma_desc_mem, *pdma_desc_mem;
|
||
|
+
|
||
|
+
|
||
|
+
|
||
|
+typedef enum _list_sts_ {
|
||
|
+ sts_free = 0,
|
||
|
+
|
||
|
+ /* RX-Y Bits 0:7 */
|
||
|
+ rx_waiting_y_intr = 0x00000001,
|
||
|
+ rx_y_error = 0x00000004,
|
||
|
+
|
||
|
+ /* RX-UV Bits 8:16 */
|
||
|
+ rx_waiting_uv_intr = 0x0000100,
|
||
|
+ rx_uv_error = 0x0000400,
|
||
|
+
|
||
|
+ rx_sts_waiting = (rx_waiting_y_intr|rx_waiting_uv_intr),
|
||
|
+ rx_sts_error = (rx_y_error|rx_uv_error),
|
||
|
+
|
||
|
+ rx_y_mask = 0x000000FF,
|
||
|
+ rx_uv_mask = 0x0000FF00,
|
||
|
+
|
||
|
+} list_sts;
|
||
|
+
|
||
|
+typedef struct _tx_dma_pkt_ {
|
||
|
+ dma_desc_mem desc_mem;
|
||
|
+ hw_comp_callback call_back;
|
||
|
+ crystalhd_dio_req *dio_req;
|
||
|
+ wait_queue_head_t *cb_event;
|
||
|
+ uint32_t list_tag;
|
||
|
+
|
||
|
+} tx_dma_pkt;
|
||
|
+
|
||
|
+typedef struct _crystalhd_rx_dma_pkt {
|
||
|
+ dma_desc_mem desc_mem;
|
||
|
+ crystalhd_dio_req *dio_req;
|
||
|
+ uint32_t pkt_tag;
|
||
|
+ uint32_t flags;
|
||
|
+ BC_PIC_INFO_BLOCK pib;
|
||
|
+ dma_addr_t uv_phy_addr;
|
||
|
+ struct _crystalhd_rx_dma_pkt *next;
|
||
|
+
|
||
|
+} crystalhd_rx_dma_pkt;
|
||
|
+
|
||
|
+struct crystalhd_hw_stats{
|
||
|
+ uint32_t rx_errors;
|
||
|
+ uint32_t tx_errors;
|
||
|
+ uint32_t freeq_count;
|
||
|
+ uint32_t rdyq_count;
|
||
|
+ uint32_t num_interrupts;
|
||
|
+ uint32_t dev_interrupts;
|
||
|
+ uint32_t cin_busy;
|
||
|
+ uint32_t pause_cnt;
|
||
|
+};
|
||
|
+
|
||
|
+struct crystalhd_hw {
|
||
|
+ tx_dma_pkt tx_pkt_pool[DMA_ENGINE_CNT];
|
||
|
+ spinlock_t lock;
|
||
|
+
|
||
|
+ uint32_t tx_ioq_tag_seed;
|
||
|
+ uint32_t tx_list_post_index;
|
||
|
+
|
||
|
+ crystalhd_rx_dma_pkt *rx_pkt_pool_head;
|
||
|
+ uint32_t rx_pkt_tag_seed;
|
||
|
+
|
||
|
+ bool dev_started;
|
||
|
+ void *adp;
|
||
|
+
|
||
|
+ wait_queue_head_t *pfw_cmd_event;
|
||
|
+ int fwcmd_evt_sts;
|
||
|
+
|
||
|
+ uint32_t pib_del_Q_addr;
|
||
|
+ uint32_t pib_rel_Q_addr;
|
||
|
+
|
||
|
+ crystalhd_dioq_t *tx_freeq;
|
||
|
+ crystalhd_dioq_t *tx_actq;
|
||
|
+
|
||
|
+ /* Rx DMA Engine Specific Locks */
|
||
|
+ spinlock_t rx_lock;
|
||
|
+ uint32_t rx_list_post_index;
|
||
|
+ list_sts rx_list_sts[DMA_ENGINE_CNT];
|
||
|
+ crystalhd_dioq_t *rx_rdyq;
|
||
|
+ crystalhd_dioq_t *rx_freeq;
|
||
|
+ crystalhd_dioq_t *rx_actq;
|
||
|
+ uint32_t stop_pending;
|
||
|
+
|
||
|
+ /* HW counters.. */
|
||
|
+ struct crystalhd_hw_stats stats;
|
||
|
+
|
||
|
+ /* Core clock in MHz */
|
||
|
+ uint32_t core_clock_mhz;
|
||
|
+ uint32_t prev_n;
|
||
|
+ uint32_t pwr_lock;
|
||
|
+};
|
||
|
+
|
||
|
+/* Clock defines for power control */
|
||
|
+#define CLOCK_PRESET 175
|
||
|
+
|
||
|
+/* DMA engine register BIT mask wrappers.. */
|
||
|
+#define DMA_START_BIT MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_MASK
|
||
|
+
|
||
|
+#define GET_RX_INTR_MASK (INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_MASK | \
|
||
|
+ INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK | \
|
||
|
+ INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_MASK | \
|
||
|
+ INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK | \
|
||
|
+ INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_MASK | \
|
||
|
+ INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK | \
|
||
|
+ INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_MASK | \
|
||
|
+ INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK)
|
||
|
+
|
||
|
+#define GET_Y0_ERR_MSK (MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK | \
|
||
|
+ MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK | \
|
||
|
+ MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK | \
|
||
|
+ MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK)
|
||
|
+
|
||
|
+#define GET_UV0_ERR_MSK (MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK | \
|
||
|
+ MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK | \
|
||
|
+ MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK | \
|
||
|
+ MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK)
|
||
|
+
|
||
|
+#define GET_Y1_ERR_MSK (MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK | \
|
||
|
+ MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK | \
|
||
|
+ MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK | \
|
||
|
+ MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK)
|
||
|
+
|
||
|
+#define GET_UV1_ERR_MSK (MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK | \
|
||
|
+ MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK | \
|
||
|
+ MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK | \
|
||
|
+ MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK)
|
||
|
+
|
||
|
+
|
||
|
+/**** API Exposed to the other layers ****/
|
||
|
+BC_STATUS crystalhd_download_fw(struct crystalhd_adp *adp,
|
||
|
+ void *buffer, uint32_t sz);
|
||
|
+BC_STATUS crystalhd_do_fw_cmd(struct crystalhd_hw *hw, BC_FW_CMD *fw_cmd);
|
||
|
+bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw);
|
||
|
+BC_STATUS crystalhd_hw_open(struct crystalhd_hw *, struct crystalhd_adp *);
|
||
|
+BC_STATUS crystalhd_hw_close(struct crystalhd_hw *);
|
||
|
+BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *);
|
||
|
+BC_STATUS crystalhd_hw_free_dma_rings(struct crystalhd_hw *);
|
||
|
+
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_post_tx(struct crystalhd_hw *hw, crystalhd_dio_req *ioreq,
|
||
|
+ hw_comp_callback call_back,
|
||
|
+ wait_queue_head_t *cb_event,
|
||
|
+ uint32_t *list_id, uint8_t data_flags);
|
||
|
+
|
||
|
+BC_STATUS crystalhd_hw_pause(struct crystalhd_hw *hw);
|
||
|
+BC_STATUS crystalhd_hw_unpause(struct crystalhd_hw *hw);
|
||
|
+BC_STATUS crystalhd_hw_suspend(struct crystalhd_hw *hw);
|
||
|
+BC_STATUS crystalhd_hw_cancel_tx(struct crystalhd_hw *hw, uint32_t list_id);
|
||
|
+BC_STATUS crystalhd_hw_add_cap_buffer(struct crystalhd_hw *hw,
|
||
|
+ crystalhd_dio_req *ioreq, bool en_post);
|
||
|
+BC_STATUS crystalhd_hw_get_cap_buffer(struct crystalhd_hw *hw,
|
||
|
+ BC_PIC_INFO_BLOCK *pib,
|
||
|
+ crystalhd_dio_req **ioreq);
|
||
|
+BC_STATUS crystalhd_hw_stop_capture(struct crystalhd_hw *hw);
|
||
|
+BC_STATUS crystalhd_hw_start_capture(struct crystalhd_hw *hw);
|
||
|
+void crystalhd_hw_stats(struct crystalhd_hw *hw, struct crystalhd_hw_stats *stats);
|
||
|
+
|
||
|
+/* API to program the core clock on the decoder */
|
||
|
+BC_STATUS crystalhd_hw_set_core_clock(struct crystalhd_hw *);
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
|
||
|
new file mode 100644
|
||
|
index 0000000..1f36b4d
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/crystalhd_lnx.c
|
||
|
@@ -0,0 +1,780 @@
|
||
|
+/***************************************************************************
|
||
|
+ * Copyright (c) 2005-2009, Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: crystalhd_lnx . c
|
||
|
+ *
|
||
|
+ * Description:
|
||
|
+ * BCM70010 Linux driver
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ **********************************************************************
|
||
|
+ * This file is part of the crystalhd device driver.
|
||
|
+ *
|
||
|
+ * This driver is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, version 2 of the License.
|
||
|
+ *
|
||
|
+ * This driver is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this driver. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ **********************************************************************/
|
||
|
+
|
||
|
+#include <linux/version.h>
|
||
|
+
|
||
|
+#include "crystalhd_lnx.h"
|
||
|
+
|
||
|
+static struct class *crystalhd_class;
|
||
|
+
|
||
|
+static struct crystalhd_adp *g_adp_info;
|
||
|
+
|
||
|
+static irqreturn_t chd_dec_isr(int irq, void *arg)
|
||
|
+{
|
||
|
+ struct crystalhd_adp *adp = (struct crystalhd_adp *) arg;
|
||
|
+ int rc = 0;
|
||
|
+ if (adp)
|
||
|
+ rc = crystalhd_cmd_interrupt(&adp->cmds);
|
||
|
+
|
||
|
+ return IRQ_RETVAL(rc);
|
||
|
+}
|
||
|
+
|
||
|
+static int chd_dec_enable_int(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ int rc = 0;
|
||
|
+
|
||
|
+ if (!adp || !adp->pdev) {
|
||
|
+ BCMLOG_ERR("Invalid arg!!\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (adp->pdev->msi_enabled)
|
||
|
+ adp->msi = 1;
|
||
|
+ else
|
||
|
+ adp->msi = pci_enable_msi(adp->pdev);
|
||
|
+
|
||
|
+ rc = request_irq(adp->pdev->irq, chd_dec_isr, IRQF_SHARED,
|
||
|
+ adp->name, (void *)adp);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("Interrupt request failed.. \n");
|
||
|
+ pci_disable_msi(adp->pdev);
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int chd_dec_disable_int(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ if (!adp || !adp->pdev) {
|
||
|
+ BCMLOG_ERR("Invalid arg!!\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ free_irq(adp->pdev->irq, adp);
|
||
|
+
|
||
|
+ if (adp->msi)
|
||
|
+ pci_disable_msi(adp->pdev);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp, bool isr)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+ crystalhd_ioctl_data *temp;
|
||
|
+
|
||
|
+ if (!adp)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ spin_lock_irqsave(&adp->lock, flags);
|
||
|
+
|
||
|
+ temp = adp->idata_free_head;
|
||
|
+ if (temp) {
|
||
|
+ adp->idata_free_head = adp->idata_free_head->next;
|
||
|
+ memset(temp, 0, sizeof(*temp));
|
||
|
+ }
|
||
|
+
|
||
|
+ spin_unlock_irqrestore(&adp->lock, flags);
|
||
|
+ return temp;
|
||
|
+}
|
||
|
+
|
||
|
+void chd_dec_free_iodata(struct crystalhd_adp *adp, crystalhd_ioctl_data *iodata,
|
||
|
+ bool isr)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+
|
||
|
+ if (!adp || !iodata)
|
||
|
+ return;
|
||
|
+
|
||
|
+ spin_lock_irqsave(&adp->lock, flags);
|
||
|
+ iodata->next = adp->idata_free_head;
|
||
|
+ adp->idata_free_head = iodata;
|
||
|
+ spin_unlock_irqrestore(&adp->lock, flags);
|
||
|
+}
|
||
|
+
|
||
|
+static inline int crystalhd_user_data(unsigned long ud, void *dr, int size, int set)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+
|
||
|
+ if (!ud || !dr) {
|
||
|
+ BCMLOG_ERR("Invalid arg \n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (set)
|
||
|
+ rc = copy_to_user((void *)ud, dr, size);
|
||
|
+ else
|
||
|
+ rc = copy_from_user(dr, (void *)ud, size);
|
||
|
+
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("Invalid args for command \n");
|
||
|
+ rc = -EFAULT;
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int chd_dec_fetch_cdata(struct crystalhd_adp *adp, crystalhd_ioctl_data *io,
|
||
|
+ uint32_t m_sz, unsigned long ua)
|
||
|
+{
|
||
|
+ unsigned long ua_off;
|
||
|
+ int rc = 0;
|
||
|
+
|
||
|
+ if (!adp || !io || !ua || !m_sz) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ io->add_cdata = vmalloc(m_sz);
|
||
|
+ if (!io->add_cdata) {
|
||
|
+ BCMLOG_ERR("kalloc fail for sz:%x\n", m_sz);
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ io->add_cdata_sz = m_sz;
|
||
|
+ ua_off = ua + sizeof(io->udata);
|
||
|
+ rc = crystalhd_user_data(ua_off, io->add_cdata, io->add_cdata_sz, 0);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("failed to pull add_cdata sz:%x ua_off:%x\n",
|
||
|
+ io->add_cdata_sz, (unsigned int)ua_off);
|
||
|
+ if (io->add_cdata) {
|
||
|
+ kfree(io->add_cdata);
|
||
|
+ io->add_cdata = NULL;
|
||
|
+ }
|
||
|
+ return -ENODATA;
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int chd_dec_release_cdata(struct crystalhd_adp *adp,
|
||
|
+ crystalhd_ioctl_data *io, unsigned long ua)
|
||
|
+{
|
||
|
+ unsigned long ua_off;
|
||
|
+ int rc;
|
||
|
+
|
||
|
+ if (!adp || !io || !ua) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (io->cmd != BCM_IOC_FW_DOWNLOAD) {
|
||
|
+ ua_off = ua + sizeof(io->udata);
|
||
|
+ rc = crystalhd_user_data(ua_off, io->add_cdata,
|
||
|
+ io->add_cdata_sz, 1);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("failed to push add_cdata sz:%x ua_off:%x\n",
|
||
|
+ io->add_cdata_sz, (unsigned int)ua_off);
|
||
|
+ return -ENODATA;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (io->add_cdata) {
|
||
|
+ vfree(io->add_cdata);
|
||
|
+ io->add_cdata = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int chd_dec_proc_user_data(struct crystalhd_adp *adp,
|
||
|
+ crystalhd_ioctl_data *io,
|
||
|
+ unsigned long ua, int set)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ uint32_t m_sz = 0;
|
||
|
+
|
||
|
+ if (!adp || !io || !ua) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ rc = crystalhd_user_data(ua, &io->udata, sizeof(io->udata), set);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("failed to %s iodata \n", (set ? "set" : "get"));
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ switch (io->cmd) {
|
||
|
+ case BCM_IOC_MEM_RD:
|
||
|
+ case BCM_IOC_MEM_WR:
|
||
|
+ case BCM_IOC_FW_DOWNLOAD:
|
||
|
+ m_sz = io->udata.u.devMem.NumDwords * 4;
|
||
|
+ if (set)
|
||
|
+ rc = chd_dec_release_cdata(adp, io, ua);
|
||
|
+ else
|
||
|
+ rc = chd_dec_fetch_cdata(adp, io, m_sz, ua);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int chd_dec_api_cmd(struct crystalhd_adp *adp, unsigned long ua,
|
||
|
+ uint32_t uid, uint32_t cmd, crystalhd_cmd_proc func)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ crystalhd_ioctl_data *temp;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ temp = chd_dec_alloc_iodata(adp, 0);
|
||
|
+ if (!temp) {
|
||
|
+ BCMLOG_ERR("Failed to get iodata..\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ temp->u_id = uid;
|
||
|
+ temp->cmd = cmd;
|
||
|
+
|
||
|
+ rc = chd_dec_proc_user_data(adp, temp, ua, 0);
|
||
|
+ if (!rc) {
|
||
|
+ sts = func(&adp->cmds, temp);
|
||
|
+ if (sts == BC_STS_PENDING)
|
||
|
+ sts = BC_STS_NOT_IMPL;
|
||
|
+ temp->udata.RetSts = sts;
|
||
|
+ rc = chd_dec_proc_user_data(adp, temp, ua, 1);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (temp) {
|
||
|
+ chd_dec_free_iodata(adp, temp, 0);
|
||
|
+ temp = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+/* ========================= API interfaces =================================*/
|
||
|
+static int chd_dec_ioctl(struct inode *in, struct file *fd,
|
||
|
+ unsigned int cmd, unsigned long ua)
|
||
|
+{
|
||
|
+ struct crystalhd_adp *adp = chd_get_adp();
|
||
|
+ crystalhd_cmd_proc cproc;
|
||
|
+ struct crystalhd_user *uc;
|
||
|
+
|
||
|
+ if (!adp || !fd) {
|
||
|
+ BCMLOG_ERR("Invalid adp\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ uc = (struct crystalhd_user *)fd->private_data;
|
||
|
+ if (!uc) {
|
||
|
+ BCMLOG_ERR("Failed to get uc\n");
|
||
|
+ return -ENODATA;
|
||
|
+ }
|
||
|
+
|
||
|
+ cproc = crystalhd_get_cmd_proc(&adp->cmds, cmd, uc);
|
||
|
+ if (!cproc) {
|
||
|
+ BCMLOG_ERR("Unhandled command: %d\n", cmd);
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ return chd_dec_api_cmd(adp, ua, uc->uid, cmd, cproc);
|
||
|
+}
|
||
|
+
|
||
|
+static int chd_dec_open(struct inode *in, struct file *fd)
|
||
|
+{
|
||
|
+ struct crystalhd_adp *adp = chd_get_adp();
|
||
|
+ int rc = 0;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ struct crystalhd_user *uc = NULL;
|
||
|
+
|
||
|
+ BCMLOG_ENTER;
|
||
|
+ if (!adp) {
|
||
|
+ BCMLOG_ERR("Invalid adp\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (adp->cfg_users >= BC_LINK_MAX_OPENS) {
|
||
|
+ BCMLOG(BCMLOG_INFO, "Already in use.%d\n", adp->cfg_users);
|
||
|
+ return -EBUSY;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_user_open(&adp->cmds, &uc);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("cmd_user_open - %d \n", sts);
|
||
|
+ rc = -EBUSY;
|
||
|
+ }
|
||
|
+
|
||
|
+ adp->cfg_users++;
|
||
|
+
|
||
|
+ fd->private_data = uc;
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int chd_dec_close(struct inode *in, struct file *fd)
|
||
|
+{
|
||
|
+ struct crystalhd_adp *adp = chd_get_adp();
|
||
|
+ struct crystalhd_user *uc;
|
||
|
+
|
||
|
+ BCMLOG_ENTER;
|
||
|
+ if (!adp) {
|
||
|
+ BCMLOG_ERR("Invalid adp \n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ uc = (struct crystalhd_user *)fd->private_data;
|
||
|
+ if (!uc) {
|
||
|
+ BCMLOG_ERR("Failed to get uc\n");
|
||
|
+ return -ENODATA;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_user_close(&adp->cmds, uc);
|
||
|
+
|
||
|
+ adp->cfg_users--;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static const struct file_operations chd_dec_fops = {
|
||
|
+ .owner = THIS_MODULE,
|
||
|
+ .ioctl = chd_dec_ioctl,
|
||
|
+ .open = chd_dec_open,
|
||
|
+ .release = chd_dec_close,
|
||
|
+};
|
||
|
+
|
||
|
+static int chd_dec_init_chdev(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ crystalhd_ioctl_data *temp;
|
||
|
+ struct device *dev;
|
||
|
+ int rc = -ENODEV, i = 0;
|
||
|
+
|
||
|
+ if (!adp)
|
||
|
+ goto fail;
|
||
|
+
|
||
|
+ adp->chd_dec_major = register_chrdev(0, CRYSTALHD_API_NAME,
|
||
|
+ &chd_dec_fops);
|
||
|
+ if (adp->chd_dec_major < 0) {
|
||
|
+ BCMLOG_ERR("Failed to create config dev\n");
|
||
|
+ rc = adp->chd_dec_major;
|
||
|
+ goto fail;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* register crystalhd class */
|
||
|
+ crystalhd_class = class_create(THIS_MODULE, "crystalhd");
|
||
|
+ if (IS_ERR(crystalhd_class)) {
|
||
|
+ BCMLOG_ERR("failed to create class\n");
|
||
|
+ goto fail;
|
||
|
+ }
|
||
|
+
|
||
|
+ dev = device_create(crystalhd_class, NULL, MKDEV(adp->chd_dec_major, 0),
|
||
|
+ NULL, "crystalhd");
|
||
|
+ if (!dev) {
|
||
|
+ BCMLOG_ERR("failed to create device\n");
|
||
|
+ goto device_create_fail;
|
||
|
+ }
|
||
|
+
|
||
|
+ rc = crystalhd_create_elem_pool(adp, BC_LINK_ELEM_POOL_SZ);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("failed to create device\n");
|
||
|
+ goto elem_pool_fail;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Allocate general purpose ioctl pool. */
|
||
|
+ for (i = 0; i < CHD_IODATA_POOL_SZ; i++) {
|
||
|
+ /* FIXME: jarod: why atomic? */
|
||
|
+ temp = kzalloc(sizeof(crystalhd_ioctl_data), GFP_ATOMIC);
|
||
|
+ if (!temp) {
|
||
|
+ BCMLOG_ERR("ioctl data pool kzalloc failed\n");
|
||
|
+ rc = -ENOMEM;
|
||
|
+ goto kzalloc_fail;
|
||
|
+ }
|
||
|
+ /* Add to global pool.. */
|
||
|
+ chd_dec_free_iodata(adp, temp, 0);
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+
|
||
|
+kzalloc_fail:
|
||
|
+ crystalhd_delete_elem_pool(adp);
|
||
|
+elem_pool_fail:
|
||
|
+ device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
|
||
|
+device_create_fail:
|
||
|
+ class_destroy(crystalhd_class);
|
||
|
+fail:
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static void chd_dec_release_chdev(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ crystalhd_ioctl_data *temp = NULL;
|
||
|
+ if (!adp)
|
||
|
+ return;
|
||
|
+
|
||
|
+ if (adp->chd_dec_major > 0) {
|
||
|
+ /* unregister crystalhd class */
|
||
|
+ device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
|
||
|
+ unregister_chrdev(adp->chd_dec_major, CRYSTALHD_API_NAME);
|
||
|
+ BCMLOG(BCMLOG_INFO, "released api device - %d\n",
|
||
|
+ adp->chd_dec_major);
|
||
|
+ class_destroy(crystalhd_class);
|
||
|
+ }
|
||
|
+ adp->chd_dec_major = 0;
|
||
|
+
|
||
|
+ /* Clear iodata pool.. */
|
||
|
+ do {
|
||
|
+ temp = chd_dec_alloc_iodata(adp, 0);
|
||
|
+ if (temp)
|
||
|
+ kfree(temp);
|
||
|
+ } while (temp);
|
||
|
+
|
||
|
+ crystalhd_delete_elem_pool(adp);
|
||
|
+}
|
||
|
+
|
||
|
+static int chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ unsigned long bar2 = pci_resource_start(pinfo->pdev, 2);
|
||
|
+ uint32_t mem_len = pci_resource_len(pinfo->pdev, 2);
|
||
|
+ unsigned long bar0 = pci_resource_start(pinfo->pdev, 0);
|
||
|
+ uint32_t i2o_len = pci_resource_len(pinfo->pdev, 0);
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_SSTEP, "bar2:0x%lx-0x%08x bar0:0x%lx-0x%08x\n",
|
||
|
+ bar2, mem_len, bar0, i2o_len);
|
||
|
+
|
||
|
+ rc = check_mem_region(bar2, mem_len);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("No valid mem region...\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ pinfo->addr = ioremap_nocache(bar2, mem_len);
|
||
|
+ if (!pinfo->addr) {
|
||
|
+ BCMLOG_ERR("Failed to remap mem region...\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ pinfo->pci_mem_start = bar2;
|
||
|
+ pinfo->pci_mem_len = mem_len;
|
||
|
+
|
||
|
+ rc = check_mem_region(bar0, i2o_len);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("No valid mem region...\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ pinfo->i2o_addr = ioremap_nocache(bar0, i2o_len);
|
||
|
+ if (!pinfo->i2o_addr) {
|
||
|
+ BCMLOG_ERR("Failed to remap mem region...\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ pinfo->pci_i2o_start = bar0;
|
||
|
+ pinfo->pci_i2o_len = i2o_len;
|
||
|
+
|
||
|
+ rc = pci_request_regions(pinfo->pdev, pinfo->name);
|
||
|
+ if (rc < 0) {
|
||
|
+ BCMLOG_ERR("Region request failed: %d\n", rc);
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_SSTEP, "Mapped addr:0x%08lx i2o_addr:0x%08lx\n",
|
||
|
+ (unsigned long)pinfo->addr, (unsigned long)pinfo->i2o_addr);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void chd_pci_release_mem(struct crystalhd_adp *pinfo)
|
||
|
+{
|
||
|
+ if (!pinfo)
|
||
|
+ return;
|
||
|
+
|
||
|
+ if (pinfo->addr)
|
||
|
+ iounmap(pinfo->addr);
|
||
|
+
|
||
|
+ if (pinfo->i2o_addr)
|
||
|
+ iounmap(pinfo->i2o_addr);
|
||
|
+
|
||
|
+ pci_release_regions(pinfo->pdev);
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static void chd_dec_pci_remove(struct pci_dev *pdev)
|
||
|
+{
|
||
|
+ struct crystalhd_adp *pinfo;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ BCMLOG_ENTER;
|
||
|
+
|
||
|
+ pinfo = (struct crystalhd_adp *) pci_get_drvdata(pdev);
|
||
|
+ if (!pinfo) {
|
||
|
+ BCMLOG_ERR("could not get adp\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_delete_cmd_context(&pinfo->cmds);
|
||
|
+ if (sts != BC_STS_SUCCESS)
|
||
|
+ BCMLOG_ERR("cmd delete :%d \n", sts);
|
||
|
+
|
||
|
+ chd_dec_release_chdev(pinfo);
|
||
|
+
|
||
|
+ chd_dec_disable_int(pinfo);
|
||
|
+
|
||
|
+ chd_pci_release_mem(pinfo);
|
||
|
+ pci_disable_device(pinfo->pdev);
|
||
|
+
|
||
|
+ kfree(pinfo);
|
||
|
+ g_adp_info = NULL;
|
||
|
+}
|
||
|
+
|
||
|
+static int chd_dec_pci_probe(struct pci_dev *pdev,
|
||
|
+ const struct pci_device_id *entry)
|
||
|
+{
|
||
|
+ struct crystalhd_adp *pinfo;
|
||
|
+ int rc;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DBG, "PCI_INFO: Vendor:0x%04x Device:0x%04x "
|
||
|
+ "s_vendor:0x%04x s_device: 0x%04x\n",
|
||
|
+ pdev->vendor, pdev->device, pdev->subsystem_vendor,
|
||
|
+ pdev->subsystem_device);
|
||
|
+
|
||
|
+ /* FIXME: jarod: why atomic? */
|
||
|
+ pinfo = kzalloc(sizeof(struct crystalhd_adp), GFP_ATOMIC);
|
||
|
+ if (!pinfo) {
|
||
|
+ BCMLOG_ERR("Failed to allocate memory\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ pinfo->pdev = pdev;
|
||
|
+
|
||
|
+ rc = pci_enable_device(pdev);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("Failed to enable PCI device\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ snprintf(pinfo->name, 31, "crystalhd_pci_e:%d:%d:%d",
|
||
|
+ pdev->bus->number, PCI_SLOT(pdev->devfn),
|
||
|
+ PCI_FUNC(pdev->devfn));
|
||
|
+
|
||
|
+ rc = chd_pci_reserve_mem(pinfo);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("Failed to setup memory regions.\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ pinfo->present = 1;
|
||
|
+ pinfo->drv_data = entry->driver_data;
|
||
|
+
|
||
|
+ /* Setup adapter level lock.. */
|
||
|
+ spin_lock_init(&pinfo->lock);
|
||
|
+
|
||
|
+ /* setup api stuff.. */
|
||
|
+ chd_dec_init_chdev(pinfo);
|
||
|
+ rc = chd_dec_enable_int(pinfo);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("_enable_int err:%d \n", rc);
|
||
|
+ pci_disable_device(pdev);
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Set dma mask... */
|
||
|
+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
|
||
|
+ pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
|
||
|
+ pinfo->dmabits = 64;
|
||
|
+ } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
|
||
|
+ pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
|
||
|
+ pinfo->dmabits = 32;
|
||
|
+ } else {
|
||
|
+ BCMLOG_ERR("Unabled to setup DMA %d\n", rc);
|
||
|
+ pci_disable_device(pdev);
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_setup_cmd_context(&pinfo->cmds, pinfo);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("cmd setup :%d \n", sts);
|
||
|
+ pci_disable_device(pdev);
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ pci_set_master(pdev);
|
||
|
+
|
||
|
+ pci_set_drvdata(pdev, pinfo);
|
||
|
+
|
||
|
+ g_adp_info = pinfo;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+#ifdef CONFIG_PM
|
||
|
+int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||
|
+{
|
||
|
+ struct crystalhd_adp *adp;
|
||
|
+ crystalhd_ioctl_data *temp;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+
|
||
|
+ adp = (struct crystalhd_adp *)pci_get_drvdata(pdev);
|
||
|
+ if (!adp) {
|
||
|
+ BCMLOG_ERR("could not get adp\n");
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ temp = chd_dec_alloc_iodata(adp, false);
|
||
|
+ if (!temp) {
|
||
|
+ BCMLOG_ERR("could not get ioctl data\n");
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_suspend(&adp->cmds, temp);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("BCM70012 Suspend %d\n", sts);
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ chd_dec_free_iodata(adp, temp, false);
|
||
|
+ chd_dec_disable_int(adp);
|
||
|
+ pci_save_state(pdev);
|
||
|
+
|
||
|
+ /* Disable IO/bus master/irq router */
|
||
|
+ pci_disable_device(pdev);
|
||
|
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int chd_dec_pci_resume(struct pci_dev *pdev)
|
||
|
+{
|
||
|
+ struct crystalhd_adp *adp;
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ int rc;
|
||
|
+
|
||
|
+ adp = (struct crystalhd_adp *)pci_get_drvdata(pdev);
|
||
|
+ if (!adp) {
|
||
|
+ BCMLOG_ERR("could not get adp\n");
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ pci_set_power_state(pdev, PCI_D0);
|
||
|
+ pci_restore_state(pdev);
|
||
|
+
|
||
|
+ /* device's irq possibly is changed, driver should take care */
|
||
|
+ if (pci_enable_device(pdev)) {
|
||
|
+ BCMLOG_ERR("Failed to enable PCI device\n");
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ pci_set_master(pdev);
|
||
|
+
|
||
|
+ rc = chd_dec_enable_int(adp);
|
||
|
+ if (rc) {
|
||
|
+ BCMLOG_ERR("_enable_int err:%d \n", rc);
|
||
|
+ pci_disable_device(pdev);
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ sts = crystalhd_resume(&adp->cmds);
|
||
|
+ if (sts != BC_STS_SUCCESS) {
|
||
|
+ BCMLOG_ERR("BCM70012 Resume %d\n", sts);
|
||
|
+ pci_disable_device(pdev);
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
+static struct pci_device_id chd_dec_pci_id_table[] = {
|
||
|
+/* vendor, device, subvendor, subdevice, class, classmask, driver_data */
|
||
|
+ { 0x14e4, 0x1612, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
|
||
|
+ { 0, },
|
||
|
+};
|
||
|
+
|
||
|
+struct pci_driver bc_chd_70012_driver = {
|
||
|
+ .name = "Broadcom 70012 Decoder",
|
||
|
+ .probe = chd_dec_pci_probe,
|
||
|
+ .remove = chd_dec_pci_remove,
|
||
|
+ .id_table = chd_dec_pci_id_table,
|
||
|
+#ifdef CONFIG_PM
|
||
|
+ .suspend = chd_dec_pci_suspend,
|
||
|
+ .resume = chd_dec_pci_resume
|
||
|
+#endif
|
||
|
+};
|
||
|
+MODULE_DEVICE_TABLE(pci, chd_dec_pci_id_table);
|
||
|
+
|
||
|
+
|
||
|
+void chd_set_log_level(struct crystalhd_adp *adp, char *arg)
|
||
|
+{
|
||
|
+ if ((!arg) || (strlen(arg) < 3))
|
||
|
+ g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA;
|
||
|
+ else if (!strncmp(arg, "sstep", 5))
|
||
|
+ g_linklog_level = BCMLOG_INFO | BCMLOG_DATA | BCMLOG_DBG |
|
||
|
+ BCMLOG_SSTEP | BCMLOG_ERROR;
|
||
|
+ else if (!strncmp(arg, "info", 4))
|
||
|
+ g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO;
|
||
|
+ else if (!strncmp(arg, "debug", 5))
|
||
|
+ g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO |
|
||
|
+ BCMLOG_DBG;
|
||
|
+ else if (!strncmp(arg, "pball", 5))
|
||
|
+ g_linklog_level = 0xFFFFFFFF & ~(BCMLOG_SPINLOCK);
|
||
|
+ else if (!strncmp(arg, "silent", 6))
|
||
|
+ g_linklog_level = 0;
|
||
|
+ else
|
||
|
+ g_linklog_level = 0;
|
||
|
+}
|
||
|
+
|
||
|
+struct crystalhd_adp *chd_get_adp(void)
|
||
|
+{
|
||
|
+ return g_adp_info;
|
||
|
+}
|
||
|
+
|
||
|
+int __init chd_dec_module_init(void)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+
|
||
|
+ chd_set_log_level(NULL, "debug");
|
||
|
+ BCMLOG(BCMLOG_DATA, "Loading crystalhd %d.%d.%d \n",
|
||
|
+ crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
|
||
|
+
|
||
|
+ rc = pci_register_driver(&bc_chd_70012_driver);
|
||
|
+
|
||
|
+ if (rc < 0)
|
||
|
+ BCMLOG_ERR("Could not find any devices. err:%d \n", rc);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+void __exit chd_dec_module_cleanup(void)
|
||
|
+{
|
||
|
+ BCMLOG(BCMLOG_DATA, "unloading crystalhd %d.%d.%d \n",
|
||
|
+ crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
|
||
|
+
|
||
|
+ pci_unregister_driver(&bc_chd_70012_driver);
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+MODULE_AUTHOR("Naren Sankar <nsankar@broadcom.com>");
|
||
|
+MODULE_AUTHOR("Prasad Bolisetty <prasadb@broadcom.com>");
|
||
|
+MODULE_DESCRIPTION(CRYSTAL_HD_NAME);
|
||
|
+MODULE_LICENSE("GPL");
|
||
|
+MODULE_ALIAS("bcm70012");
|
||
|
+
|
||
|
+module_init(chd_dec_module_init);
|
||
|
+module_exit(chd_dec_module_cleanup);
|
||
|
+
|
||
|
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.h b/drivers/staging/crystalhd/crystalhd_lnx.h
|
||
|
new file mode 100644
|
||
|
index 0000000..d3f9fc4
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/crystalhd_lnx.h
|
||
|
@@ -0,0 +1,96 @@
|
||
|
+/***************************************************************************
|
||
|
+ * Copyright (c) 2005-2009, Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: crystalhd_lnx . c
|
||
|
+ *
|
||
|
+ * Description:
|
||
|
+ * BCM70012 Linux driver
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ **********************************************************************
|
||
|
+ * This file is part of the crystalhd device driver.
|
||
|
+ *
|
||
|
+ * This driver is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, version 2 of the License.
|
||
|
+ *
|
||
|
+ * This driver is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this driver. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ **********************************************************************/
|
||
|
+
|
||
|
+#ifndef _CRYSTALHD_LNX_H_
|
||
|
+#define _CRYSTALHD_LNX_H_
|
||
|
+
|
||
|
+#include <linux/module.h>
|
||
|
+#include <linux/kernel.h>
|
||
|
+#include <linux/errno.h>
|
||
|
+#include <linux/string.h>
|
||
|
+#include <linux/mm.h>
|
||
|
+#include <linux/tty.h>
|
||
|
+#include <linux/slab.h>
|
||
|
+#include <linux/delay.h>
|
||
|
+#include <linux/fb.h>
|
||
|
+#include <linux/pci.h>
|
||
|
+#include <linux/init.h>
|
||
|
+#include <linux/interrupt.h>
|
||
|
+#include <linux/pagemap.h>
|
||
|
+#include <linux/vmalloc.h>
|
||
|
+
|
||
|
+#include <asm/io.h>
|
||
|
+#include <asm/irq.h>
|
||
|
+#include <asm/pgtable.h>
|
||
|
+#include <asm/system.h>
|
||
|
+#include <asm/uaccess.h>
|
||
|
+
|
||
|
+#include "crystalhd_cmds.h"
|
||
|
+
|
||
|
+#define CRYSTAL_HD_NAME "Broadcom Crystal HD Decoder (BCM70012) Driver"
|
||
|
+
|
||
|
+
|
||
|
+/* OS specific PCI information structure and adapter information. */
|
||
|
+struct crystalhd_adp {
|
||
|
+ /* Hardware borad/PCI specifics */
|
||
|
+ char name[32];
|
||
|
+ struct pci_dev *pdev;
|
||
|
+
|
||
|
+ unsigned long pci_mem_start;
|
||
|
+ uint32_t pci_mem_len;
|
||
|
+ void *addr;
|
||
|
+
|
||
|
+ unsigned long pci_i2o_start;
|
||
|
+ uint32_t pci_i2o_len;
|
||
|
+ void *i2o_addr;
|
||
|
+
|
||
|
+ unsigned int drv_data;
|
||
|
+ unsigned int dmabits; /* 32 | 64 */
|
||
|
+ unsigned int registered;
|
||
|
+ unsigned int present;
|
||
|
+ unsigned int msi;
|
||
|
+
|
||
|
+ spinlock_t lock;
|
||
|
+
|
||
|
+ /* API Related */
|
||
|
+ unsigned int chd_dec_major;
|
||
|
+ unsigned int cfg_users;
|
||
|
+
|
||
|
+ crystalhd_ioctl_data *idata_free_head; /* ioctl data pool */
|
||
|
+ crystalhd_elem_t *elem_pool_head; /* Queue element pool */
|
||
|
+
|
||
|
+ struct crystalhd_cmd cmds;
|
||
|
+
|
||
|
+ crystalhd_dio_req *ua_map_free_head;
|
||
|
+ struct pci_pool *fill_byte_pool;
|
||
|
+};
|
||
|
+
|
||
|
+
|
||
|
+struct crystalhd_adp *chd_get_adp(void);
|
||
|
+void chd_set_log_level(struct crystalhd_adp *adp, char *arg);
|
||
|
+
|
||
|
+#endif
|
||
|
+
|
||
|
diff --git a/drivers/staging/crystalhd/crystalhd_misc.c b/drivers/staging/crystalhd/crystalhd_misc.c
|
||
|
new file mode 100644
|
||
|
index 0000000..32e632c
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/crystalhd_misc.c
|
||
|
@@ -0,0 +1,1029 @@
|
||
|
+/***************************************************************************
|
||
|
+ * Copyright (c) 2005-2009, Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: crystalhd_misc . c
|
||
|
+ *
|
||
|
+ * Description:
|
||
|
+ * BCM70012 Linux driver misc routines.
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ **********************************************************************
|
||
|
+ * This file is part of the crystalhd device driver.
|
||
|
+ *
|
||
|
+ * This driver is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, version 2 of the License.
|
||
|
+ *
|
||
|
+ * This driver is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this driver. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ **********************************************************************/
|
||
|
+
|
||
|
+#include "crystalhd_misc.h"
|
||
|
+#include "crystalhd_lnx.h"
|
||
|
+
|
||
|
+uint32_t g_linklog_level;
|
||
|
+
|
||
|
+static inline uint32_t crystalhd_dram_rd(struct crystalhd_adp *adp, uint32_t mem_off)
|
||
|
+{
|
||
|
+ crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
|
||
|
+ return bc_dec_reg_rd(adp, (0x00380000 | (mem_off & 0x0007FFFF)));
|
||
|
+}
|
||
|
+
|
||
|
+static inline void crystalhd_dram_wr(struct crystalhd_adp *adp, uint32_t mem_off, uint32_t val)
|
||
|
+{
|
||
|
+ crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
|
||
|
+ bc_dec_reg_wr(adp, (0x00380000 | (mem_off & 0x0007FFFF)), val);
|
||
|
+}
|
||
|
+
|
||
|
+static inline BC_STATUS bc_chk_dram_range(struct crystalhd_adp *adp, uint32_t start_off, uint32_t cnt)
|
||
|
+{
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static crystalhd_dio_req *crystalhd_alloc_dio(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+ crystalhd_dio_req *temp = NULL;
|
||
|
+
|
||
|
+ if (!adp) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return temp;
|
||
|
+ }
|
||
|
+
|
||
|
+ spin_lock_irqsave(&adp->lock, flags);
|
||
|
+ temp = adp->ua_map_free_head;
|
||
|
+ if (temp)
|
||
|
+ adp->ua_map_free_head = adp->ua_map_free_head->next;
|
||
|
+ spin_unlock_irqrestore(&adp->lock, flags);
|
||
|
+
|
||
|
+ return temp;
|
||
|
+}
|
||
|
+
|
||
|
+static void crystalhd_free_dio(struct crystalhd_adp *adp, crystalhd_dio_req *dio)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+
|
||
|
+ if (!adp || !dio)
|
||
|
+ return;
|
||
|
+ spin_lock_irqsave(&adp->lock, flags);
|
||
|
+ dio->sig = crystalhd_dio_inv;
|
||
|
+ dio->page_cnt = 0;
|
||
|
+ dio->fb_size = 0;
|
||
|
+ memset(&dio->uinfo, 0, sizeof(dio->uinfo));
|
||
|
+ dio->next = adp->ua_map_free_head;
|
||
|
+ adp->ua_map_free_head = dio;
|
||
|
+ spin_unlock_irqrestore(&adp->lock, flags);
|
||
|
+}
|
||
|
+
|
||
|
+static crystalhd_elem_t *crystalhd_alloc_elem(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+ crystalhd_elem_t *temp = NULL;
|
||
|
+
|
||
|
+ if (!adp)
|
||
|
+ return temp;
|
||
|
+ spin_lock_irqsave(&adp->lock, flags);
|
||
|
+ temp = adp->elem_pool_head;
|
||
|
+ if (temp) {
|
||
|
+ adp->elem_pool_head = adp->elem_pool_head->flink;
|
||
|
+ memset(temp, 0, sizeof(*temp));
|
||
|
+ }
|
||
|
+ spin_unlock_irqrestore(&adp->lock, flags);
|
||
|
+
|
||
|
+ return temp;
|
||
|
+}
|
||
|
+static void crystalhd_free_elem(struct crystalhd_adp *adp, crystalhd_elem_t *elem)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+
|
||
|
+ if (!adp || !elem)
|
||
|
+ return;
|
||
|
+ spin_lock_irqsave(&adp->lock, flags);
|
||
|
+ elem->flink = adp->elem_pool_head;
|
||
|
+ adp->elem_pool_head = elem;
|
||
|
+ spin_unlock_irqrestore(&adp->lock, flags);
|
||
|
+}
|
||
|
+
|
||
|
+static inline void crystalhd_set_sg(struct scatterlist *sg, struct page *page,
|
||
|
+ unsigned int len, unsigned int offset)
|
||
|
+{
|
||
|
+ sg_set_page(sg, page, len, offset);
|
||
|
+#ifdef CONFIG_X86_64
|
||
|
+ sg->dma_length = len;
|
||
|
+#endif
|
||
|
+}
|
||
|
+
|
||
|
+static inline void crystalhd_init_sg(struct scatterlist *sg, unsigned int entries)
|
||
|
+{
|
||
|
+ /* http://lkml.org/lkml/2007/11/27/68 */
|
||
|
+ sg_init_table(sg, entries);
|
||
|
+}
|
||
|
+
|
||
|
+/*========================== Extern ========================================*/
|
||
|
+/**
|
||
|
+ * bc_dec_reg_rd - Read 7412's device register.
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @reg_off: Register offset.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * 32bit value read
|
||
|
+ *
|
||
|
+ * 7412's device register read routine. This interface use
|
||
|
+ * 7412's device access range mapped from BAR-2 (4M) of PCIe
|
||
|
+ * configuration space.
|
||
|
+ */
|
||
|
+uint32_t bc_dec_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
|
||
|
+{
|
||
|
+ if (!adp || (reg_off > adp->pci_mem_len)) {
|
||
|
+ BCMLOG_ERR("dec_rd_reg_off outof range: 0x%08x\n", reg_off);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ return readl(adp->addr + reg_off);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * bc_dec_reg_wr - Write 7412's device register
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @reg_off: Register offset.
|
||
|
+ * @val: Dword value to be written.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * none.
|
||
|
+ *
|
||
|
+ * 7412's device register write routine. This interface use
|
||
|
+ * 7412's device access range mapped from BAR-2 (4M) of PCIe
|
||
|
+ * configuration space.
|
||
|
+ */
|
||
|
+void bc_dec_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
|
||
|
+{
|
||
|
+ if (!adp || (reg_off > adp->pci_mem_len)) {
|
||
|
+ BCMLOG_ERR("dec_wr_reg_off outof range: 0x%08x\n", reg_off);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ writel(val, adp->addr + reg_off);
|
||
|
+ udelay(8);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_reg_rd - Read Link's device register.
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @reg_off: Register offset.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * 32bit value read
|
||
|
+ *
|
||
|
+ * Link device register read routine. This interface use
|
||
|
+ * Link's device access range mapped from BAR-1 (64K) of PCIe
|
||
|
+ * configuration space.
|
||
|
+ *
|
||
|
+ */
|
||
|
+uint32_t crystalhd_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
|
||
|
+{
|
||
|
+ if (!adp || (reg_off > adp->pci_i2o_len)) {
|
||
|
+ BCMLOG_ERR("link_rd_reg_off outof range: 0x%08x\n", reg_off);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ return readl(adp->i2o_addr + reg_off);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_reg_wr - Write Link's device register
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @reg_off: Register offset.
|
||
|
+ * @val: Dword value to be written.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * none.
|
||
|
+ *
|
||
|
+ * Link device register write routine. This interface use
|
||
|
+ * Link's device access range mapped from BAR-1 (64K) of PCIe
|
||
|
+ * configuration space.
|
||
|
+ *
|
||
|
+ */
|
||
|
+void crystalhd_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
|
||
|
+{
|
||
|
+ if (!adp || (reg_off > adp->pci_i2o_len)) {
|
||
|
+ BCMLOG_ERR("link_wr_reg_off outof range: 0x%08x\n", reg_off);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ writel(val, adp->i2o_addr + reg_off);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_mem_rd - Read data from 7412's DRAM area.
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @start_off: Start offset.
|
||
|
+ * @dw_cnt: Count in dwords.
|
||
|
+ * @rd_buff: Buffer to copy the data from dram.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * Status.
|
||
|
+ *
|
||
|
+ * 7412's Dram read routine.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *adp, uint32_t start_off,
|
||
|
+ uint32_t dw_cnt, uint32_t *rd_buff)
|
||
|
+{
|
||
|
+ uint32_t ix = 0;
|
||
|
+
|
||
|
+ if (!adp || !rd_buff ||
|
||
|
+ (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
|
||
|
+ BCMLOG_ERR("Invalid arg \n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+ for (ix = 0; ix < dw_cnt; ix++)
|
||
|
+ rd_buff[ix] = crystalhd_dram_rd(adp, (start_off + (ix * 4)));
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_mem_wr - Write data to 7412's DRAM area.
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @start_off: Start offset.
|
||
|
+ * @dw_cnt: Count in dwords.
|
||
|
+ * @wr_buff: Data Buffer to be written.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * Status.
|
||
|
+ *
|
||
|
+ * 7412's Dram write routine.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *adp, uint32_t start_off,
|
||
|
+ uint32_t dw_cnt, uint32_t *wr_buff)
|
||
|
+{
|
||
|
+ uint32_t ix = 0;
|
||
|
+
|
||
|
+ if (!adp || !wr_buff ||
|
||
|
+ (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
|
||
|
+ BCMLOG_ERR("Invalid arg \n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (ix = 0; ix < dw_cnt; ix++)
|
||
|
+ crystalhd_dram_wr(adp, (start_off + (ix * 4)), wr_buff[ix]);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+/**
|
||
|
+ * crystalhd_pci_cfg_rd - PCIe config read
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @off: PCI config space offset.
|
||
|
+ * @len: Size -- Byte, Word & dword.
|
||
|
+ * @val: Value read
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * Status.
|
||
|
+ *
|
||
|
+ * Get value from Link's PCIe config space.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *adp, uint32_t off,
|
||
|
+ uint32_t len, uint32_t *val)
|
||
|
+{
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ int rc = 0;
|
||
|
+
|
||
|
+ if (!adp || !val) {
|
||
|
+ BCMLOG_ERR("Invalid arg \n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ switch (len) {
|
||
|
+ case 1:
|
||
|
+ rc = pci_read_config_byte(adp->pdev, off, (u8 *)val);
|
||
|
+ break;
|
||
|
+ case 2:
|
||
|
+ rc = pci_read_config_word(adp->pdev, off, (u16 *)val);
|
||
|
+ break;
|
||
|
+ case 4:
|
||
|
+ rc = pci_read_config_dword(adp->pdev, off, (u32 *)val);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ rc = -EINVAL;
|
||
|
+ sts = BC_STS_INV_ARG;
|
||
|
+ BCMLOG_ERR("Invalid len:%d\n", len);
|
||
|
+ };
|
||
|
+
|
||
|
+ if (rc && (sts == BC_STS_SUCCESS))
|
||
|
+ sts = BC_STS_ERROR;
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_pci_cfg_wr - PCIe config write
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @off: PCI config space offset.
|
||
|
+ * @len: Size -- Byte, Word & dword.
|
||
|
+ * @val: Value to be written
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * Status.
|
||
|
+ *
|
||
|
+ * Set value to Link's PCIe config space.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *adp, uint32_t off,
|
||
|
+ uint32_t len, uint32_t val)
|
||
|
+{
|
||
|
+ BC_STATUS sts = BC_STS_SUCCESS;
|
||
|
+ int rc = 0;
|
||
|
+
|
||
|
+ if (!adp || !val) {
|
||
|
+ BCMLOG_ERR("Invalid arg \n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ switch (len) {
|
||
|
+ case 1:
|
||
|
+ rc = pci_write_config_byte(adp->pdev, off, (u8)val);
|
||
|
+ break;
|
||
|
+ case 2:
|
||
|
+ rc = pci_write_config_word(adp->pdev, off, (u16)val);
|
||
|
+ break;
|
||
|
+ case 4:
|
||
|
+ rc = pci_write_config_dword(adp->pdev, off, val);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ rc = -EINVAL;
|
||
|
+ sts = BC_STS_INV_ARG;
|
||
|
+ BCMLOG_ERR("Invalid len:%d\n", len);
|
||
|
+ };
|
||
|
+
|
||
|
+ if (rc && (sts == BC_STS_SUCCESS))
|
||
|
+ sts = BC_STS_ERROR;
|
||
|
+
|
||
|
+ return sts;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * bc_kern_dma_alloc - Allocate memory for Dma rings
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @sz: Size of the memory to allocate.
|
||
|
+ * @phy_addr: Physical address of the memory allocated.
|
||
|
+ * Typedef to system's dma_addr_t (u64)
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * Pointer to allocated memory..
|
||
|
+ *
|
||
|
+ * Wrapper to Linux kernel interface.
|
||
|
+ *
|
||
|
+ */
|
||
|
+void *bc_kern_dma_alloc(struct crystalhd_adp *adp, uint32_t sz,
|
||
|
+ dma_addr_t *phy_addr)
|
||
|
+{
|
||
|
+ void *temp = NULL;
|
||
|
+
|
||
|
+ if (!adp || !sz || !phy_addr) {
|
||
|
+ BCMLOG_ERR("Invalide Arg..\n");
|
||
|
+ return temp;
|
||
|
+ }
|
||
|
+
|
||
|
+ temp = pci_alloc_consistent(adp->pdev, sz, phy_addr);
|
||
|
+ if (temp)
|
||
|
+ memset(temp, 0, sz);
|
||
|
+
|
||
|
+ return temp;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * bc_kern_dma_free - Release Dma ring memory.
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @sz: Size of the memory to allocate.
|
||
|
+ * @ka: Kernel virtual address returned during _dio_alloc()
|
||
|
+ * @phy_addr: Physical address of the memory allocated.
|
||
|
+ * Typedef to system's dma_addr_t (u64)
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * none.
|
||
|
+ */
|
||
|
+void bc_kern_dma_free(struct crystalhd_adp *adp, uint32_t sz, void *ka,
|
||
|
+ dma_addr_t phy_addr)
|
||
|
+{
|
||
|
+ if (!adp || !ka || !sz || !phy_addr) {
|
||
|
+ BCMLOG_ERR("Invalide Arg..\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ pci_free_consistent(adp->pdev, sz, ka, phy_addr);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_create_dioq - Create Generic DIO queue
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @dioq_hnd: Handle to the dio queue created
|
||
|
+ * @cb : Optional - Call back To free the element.
|
||
|
+ * @cbctx: Context to pass to callback.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * status
|
||
|
+ *
|
||
|
+ * Initialize Generic DIO queue to hold any data. Callback
|
||
|
+ * will be used to free elements while deleting the queue.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *adp,
|
||
|
+ crystalhd_dioq_t **dioq_hnd,
|
||
|
+ crystalhd_data_free_cb cb, void *cbctx)
|
||
|
+{
|
||
|
+ crystalhd_dioq_t *dioq = NULL;
|
||
|
+
|
||
|
+ if (!adp || !dioq_hnd) {
|
||
|
+ BCMLOG_ERR("Invalid arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ dioq = kzalloc(sizeof(*dioq), GFP_KERNEL);
|
||
|
+ if (!dioq)
|
||
|
+ return BC_STS_INSUFF_RES;
|
||
|
+
|
||
|
+ spin_lock_init(&dioq->lock);
|
||
|
+ dioq->sig = BC_LINK_DIOQ_SIG;
|
||
|
+ dioq->head = (crystalhd_elem_t *)&dioq->head;
|
||
|
+ dioq->tail = (crystalhd_elem_t *)&dioq->head;
|
||
|
+ crystalhd_create_event(&dioq->event);
|
||
|
+ dioq->adp = adp;
|
||
|
+ dioq->data_rel_cb = cb;
|
||
|
+ dioq->cb_context = cbctx;
|
||
|
+ *dioq_hnd = dioq;
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_delete_dioq - Delete Generic DIO queue
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @dioq: DIOQ instance..
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * None.
|
||
|
+ *
|
||
|
+ * Release Generic DIO queue. This function will remove
|
||
|
+ * all the entries from the Queue and will release data
|
||
|
+ * by calling the call back provided during creation.
|
||
|
+ *
|
||
|
+ */
|
||
|
+void crystalhd_delete_dioq(struct crystalhd_adp *adp, crystalhd_dioq_t *dioq)
|
||
|
+{
|
||
|
+ void *temp;
|
||
|
+
|
||
|
+ if (!dioq || (dioq->sig != BC_LINK_DIOQ_SIG))
|
||
|
+ return;
|
||
|
+
|
||
|
+ do {
|
||
|
+ temp = crystalhd_dioq_fetch(dioq);
|
||
|
+ if (temp && dioq->data_rel_cb)
|
||
|
+ dioq->data_rel_cb(dioq->cb_context, temp);
|
||
|
+ } while (temp);
|
||
|
+ dioq->sig = 0;
|
||
|
+ kfree(dioq);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_dioq_add - Add new DIO request element.
|
||
|
+ * @ioq: DIO queue instance
|
||
|
+ * @t: DIO request to be added.
|
||
|
+ * @wake: True - Wake up suspended process.
|
||
|
+ * @tag: Special tag to assign - For search and get.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * Status.
|
||
|
+ *
|
||
|
+ * Insert new element to Q tail.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_dioq_add(crystalhd_dioq_t *ioq, void *data,
|
||
|
+ bool wake, uint32_t tag)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+ crystalhd_elem_t *tmp;
|
||
|
+
|
||
|
+ if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !data) {
|
||
|
+ BCMLOG_ERR("Invalid arg!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ tmp = crystalhd_alloc_elem(ioq->adp);
|
||
|
+ if (!tmp) {
|
||
|
+ BCMLOG_ERR("No free elements.\n");
|
||
|
+ return BC_STS_INSUFF_RES;
|
||
|
+ }
|
||
|
+
|
||
|
+ tmp->data = data;
|
||
|
+ tmp->tag = tag;
|
||
|
+ spin_lock_irqsave(&ioq->lock, flags);
|
||
|
+ tmp->flink = (crystalhd_elem_t *)&ioq->head;
|
||
|
+ tmp->blink = ioq->tail;
|
||
|
+ tmp->flink->blink = tmp;
|
||
|
+ tmp->blink->flink = tmp;
|
||
|
+ ioq->count++;
|
||
|
+ spin_unlock_irqrestore(&ioq->lock, flags);
|
||
|
+
|
||
|
+ if (wake)
|
||
|
+ crystalhd_set_event(&ioq->event);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_dioq_fetch - Fetch element from head.
|
||
|
+ * @ioq: DIO queue instance
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * data element from the head..
|
||
|
+ *
|
||
|
+ * Remove an element from Queue.
|
||
|
+ */
|
||
|
+void *crystalhd_dioq_fetch(crystalhd_dioq_t *ioq)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+ crystalhd_elem_t *tmp;
|
||
|
+ crystalhd_elem_t *ret = NULL;
|
||
|
+ void *data = NULL;
|
||
|
+
|
||
|
+ if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
|
||
|
+ BCMLOG_ERR("Invalid arg!!\n");
|
||
|
+ return data;
|
||
|
+ }
|
||
|
+
|
||
|
+ spin_lock_irqsave(&ioq->lock, flags);
|
||
|
+ tmp = ioq->head;
|
||
|
+ if (tmp != (crystalhd_elem_t *)&ioq->head) {
|
||
|
+ ret = tmp;
|
||
|
+ tmp->flink->blink = tmp->blink;
|
||
|
+ tmp->blink->flink = tmp->flink;
|
||
|
+ ioq->count--;
|
||
|
+ }
|
||
|
+ spin_unlock_irqrestore(&ioq->lock, flags);
|
||
|
+ if (ret) {
|
||
|
+ data = ret->data;
|
||
|
+ crystalhd_free_elem(ioq->adp, ret);
|
||
|
+ }
|
||
|
+
|
||
|
+ return data;
|
||
|
+}
|
||
|
+/**
|
||
|
+ * crystalhd_dioq_find_and_fetch - Search the tag and Fetch element
|
||
|
+ * @ioq: DIO queue instance
|
||
|
+ * @tag: Tag to search for.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * element from the head..
|
||
|
+ *
|
||
|
+ * Search TAG and remove the element.
|
||
|
+ */
|
||
|
+void *crystalhd_dioq_find_and_fetch(crystalhd_dioq_t *ioq, uint32_t tag)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+ crystalhd_elem_t *tmp;
|
||
|
+ crystalhd_elem_t *ret = NULL;
|
||
|
+ void *data = NULL;
|
||
|
+
|
||
|
+ if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
|
||
|
+ BCMLOG_ERR("Invalid arg!!\n");
|
||
|
+ return data;
|
||
|
+ }
|
||
|
+
|
||
|
+ spin_lock_irqsave(&ioq->lock, flags);
|
||
|
+ tmp = ioq->head;
|
||
|
+ while (tmp != (crystalhd_elem_t *)&ioq->head) {
|
||
|
+ if (tmp->tag == tag) {
|
||
|
+ ret = tmp;
|
||
|
+ tmp->flink->blink = tmp->blink;
|
||
|
+ tmp->blink->flink = tmp->flink;
|
||
|
+ ioq->count--;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ tmp = tmp->flink;
|
||
|
+ }
|
||
|
+ spin_unlock_irqrestore(&ioq->lock, flags);
|
||
|
+
|
||
|
+ if (ret) {
|
||
|
+ data = ret->data;
|
||
|
+ crystalhd_free_elem(ioq->adp, ret);
|
||
|
+ }
|
||
|
+
|
||
|
+ return data;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_dioq_fetch_wait - Fetch element from Head.
|
||
|
+ * @ioq: DIO queue instance
|
||
|
+ * @to_secs: Wait timeout in seconds..
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * element from the head..
|
||
|
+ *
|
||
|
+ * Return element from head if Q is not empty. Wait for new element
|
||
|
+ * if Q is empty for Timeout seconds.
|
||
|
+ */
|
||
|
+void *crystalhd_dioq_fetch_wait(crystalhd_dioq_t *ioq, uint32_t to_secs,
|
||
|
+ uint32_t *sig_pend)
|
||
|
+{
|
||
|
+ unsigned long flags = 0;
|
||
|
+ int rc = 0, count;
|
||
|
+ void *tmp = NULL;
|
||
|
+
|
||
|
+ if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !to_secs || !sig_pend) {
|
||
|
+ BCMLOG_ERR("Invalid arg!!\n");
|
||
|
+ return tmp;
|
||
|
+ }
|
||
|
+
|
||
|
+ count = to_secs;
|
||
|
+ spin_lock_irqsave(&ioq->lock, flags);
|
||
|
+ while ((ioq->count == 0) && count) {
|
||
|
+ spin_unlock_irqrestore(&ioq->lock, flags);
|
||
|
+
|
||
|
+ crystalhd_wait_on_event(&ioq->event, (ioq->count > 0), 1000, rc, 0);
|
||
|
+ if (rc == 0) {
|
||
|
+ goto out;
|
||
|
+ } else if (rc == -EINTR) {
|
||
|
+ BCMLOG(BCMLOG_INFO, "Cancelling fetch wait\n");
|
||
|
+ *sig_pend = 1;
|
||
|
+ return tmp;
|
||
|
+ }
|
||
|
+ spin_lock_irqsave(&ioq->lock, flags);
|
||
|
+ count--;
|
||
|
+ }
|
||
|
+ spin_unlock_irqrestore(&ioq->lock, flags);
|
||
|
+
|
||
|
+out:
|
||
|
+ return crystalhd_dioq_fetch(ioq);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_map_dio - Map user address for DMA
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @ubuff: User buffer to map.
|
||
|
+ * @ubuff_sz: User buffer size.
|
||
|
+ * @uv_offset: UV buffer offset.
|
||
|
+ * @en_422mode: TRUE:422 FALSE:420 Capture mode.
|
||
|
+ * @dir_tx: TRUE for Tx (To device from host)
|
||
|
+ * @dio_hnd: Handle to mapped DIO request.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * Status.
|
||
|
+ *
|
||
|
+ * This routine maps user address and lock pages for DMA.
|
||
|
+ *
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_map_dio(struct crystalhd_adp *adp, void *ubuff,
|
||
|
+ uint32_t ubuff_sz, uint32_t uv_offset,
|
||
|
+ bool en_422mode, bool dir_tx,
|
||
|
+ crystalhd_dio_req **dio_hnd)
|
||
|
+{
|
||
|
+ crystalhd_dio_req *dio;
|
||
|
+ /* FIXME: jarod: should some of these unsigned longs be uint32_t or uintptr_t? */
|
||
|
+ unsigned long start = 0, end = 0, uaddr = 0, count = 0;
|
||
|
+ unsigned long spsz = 0, uv_start = 0;
|
||
|
+ int i = 0, rw = 0, res = 0, nr_pages = 0, skip_fb_sg = 0;
|
||
|
+
|
||
|
+ if (!adp || !ubuff || !ubuff_sz || !dio_hnd) {
|
||
|
+ BCMLOG_ERR("Invalid arg \n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+ /* Compute pages */
|
||
|
+ uaddr = (unsigned long)ubuff;
|
||
|
+ count = (unsigned long)ubuff_sz;
|
||
|
+ end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||
|
+ start = uaddr >> PAGE_SHIFT;
|
||
|
+ nr_pages = end - start;
|
||
|
+
|
||
|
+ if (!count || ((uaddr + count) < uaddr)) {
|
||
|
+ BCMLOG_ERR("User addr overflow!!\n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ dio = crystalhd_alloc_dio(adp);
|
||
|
+ if (!dio) {
|
||
|
+ BCMLOG_ERR("dio pool empty..\n");
|
||
|
+ return BC_STS_INSUFF_RES;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (dir_tx) {
|
||
|
+ rw = WRITE;
|
||
|
+ dio->direction = DMA_TO_DEVICE;
|
||
|
+ } else {
|
||
|
+ rw = READ;
|
||
|
+ dio->direction = DMA_FROM_DEVICE;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (nr_pages > dio->max_pages) {
|
||
|
+ BCMLOG_ERR("max_pages(%d) exceeded(%d)!!\n",
|
||
|
+ dio->max_pages, nr_pages);
|
||
|
+ crystalhd_unmap_dio(adp, dio);
|
||
|
+ return BC_STS_INSUFF_RES;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (uv_offset) {
|
||
|
+ uv_start = (uaddr + (unsigned long)uv_offset) >> PAGE_SHIFT;
|
||
|
+ dio->uinfo.uv_sg_ix = uv_start - start;
|
||
|
+ dio->uinfo.uv_sg_off = ((uaddr + (unsigned long)uv_offset) & ~PAGE_MASK);
|
||
|
+ }
|
||
|
+
|
||
|
+ dio->fb_size = ubuff_sz & 0x03;
|
||
|
+ if (dio->fb_size) {
|
||
|
+ res = copy_from_user(dio->fb_va,
|
||
|
+ (void *)(uaddr + count - dio->fb_size),
|
||
|
+ dio->fb_size);
|
||
|
+ if (res) {
|
||
|
+ BCMLOG_ERR("failed %d to copy %u fill bytes from %p\n",
|
||
|
+ res, dio->fb_size,
|
||
|
+ (void *)(uaddr + count-dio->fb_size));
|
||
|
+ crystalhd_unmap_dio(adp, dio);
|
||
|
+ return BC_STS_INSUFF_RES;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ down_read(¤t->mm->mmap_sem);
|
||
|
+ res = get_user_pages(current, current->mm, uaddr, nr_pages, rw == READ,
|
||
|
+ 0, dio->pages, NULL);
|
||
|
+ up_read(¤t->mm->mmap_sem);
|
||
|
+
|
||
|
+ /* Save for release..*/
|
||
|
+ dio->sig = crystalhd_dio_locked;
|
||
|
+ if (res < nr_pages) {
|
||
|
+ BCMLOG_ERR("get pages failed: %d-%d\n", nr_pages, res);
|
||
|
+ dio->page_cnt = res;
|
||
|
+ crystalhd_unmap_dio(adp, dio);
|
||
|
+ return BC_STS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ dio->page_cnt = nr_pages;
|
||
|
+ /* Get scatter/gather */
|
||
|
+ crystalhd_init_sg(dio->sg, dio->page_cnt);
|
||
|
+ crystalhd_set_sg(&dio->sg[0], dio->pages[0], 0, uaddr & ~PAGE_MASK);
|
||
|
+ if (nr_pages > 1) {
|
||
|
+ dio->sg[0].length = PAGE_SIZE - dio->sg[0].offset;
|
||
|
+
|
||
|
+#ifdef CONFIG_X86_64
|
||
|
+ dio->sg[0].dma_length = dio->sg[0].length;
|
||
|
+#endif
|
||
|
+ count -= dio->sg[0].length;
|
||
|
+ for (i = 1; i < nr_pages; i++) {
|
||
|
+ if (count < 4) {
|
||
|
+ spsz = count;
|
||
|
+ skip_fb_sg = 1;
|
||
|
+ } else {
|
||
|
+ spsz = (count < PAGE_SIZE) ?
|
||
|
+ (count & ~0x03) : PAGE_SIZE;
|
||
|
+ }
|
||
|
+ crystalhd_set_sg(&dio->sg[i], dio->pages[i], spsz, 0);
|
||
|
+ count -= spsz;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ if (count < 4) {
|
||
|
+ dio->sg[0].length = count;
|
||
|
+ skip_fb_sg = 1;
|
||
|
+ } else {
|
||
|
+ dio->sg[0].length = count - dio->fb_size;
|
||
|
+ }
|
||
|
+#ifdef CONFIG_X86_64
|
||
|
+ dio->sg[0].dma_length = dio->sg[0].length;
|
||
|
+#endif
|
||
|
+ }
|
||
|
+ dio->sg_cnt = pci_map_sg(adp->pdev, dio->sg,
|
||
|
+ dio->page_cnt, dio->direction);
|
||
|
+ if (dio->sg_cnt <= 0) {
|
||
|
+ BCMLOG_ERR("sg map %d-%d \n", dio->sg_cnt, dio->page_cnt);
|
||
|
+ crystalhd_unmap_dio(adp, dio);
|
||
|
+ return BC_STS_ERROR;
|
||
|
+ }
|
||
|
+ if (dio->sg_cnt && skip_fb_sg)
|
||
|
+ dio->sg_cnt -= 1;
|
||
|
+ dio->sig = crystalhd_dio_sg_mapped;
|
||
|
+ /* Fill in User info.. */
|
||
|
+ dio->uinfo.xfr_len = ubuff_sz;
|
||
|
+ dio->uinfo.xfr_buff = ubuff;
|
||
|
+ dio->uinfo.uv_offset = uv_offset;
|
||
|
+ dio->uinfo.b422mode = en_422mode;
|
||
|
+ dio->uinfo.dir_tx = dir_tx;
|
||
|
+
|
||
|
+ *dio_hnd = dio;
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_unmap_sgl - Release mapped resources
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @dio: DIO request instance
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * Status.
|
||
|
+ *
|
||
|
+ * This routine is to unmap the user buffer pages.
|
||
|
+ */
|
||
|
+BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *adp, crystalhd_dio_req *dio)
|
||
|
+{
|
||
|
+ struct page *page = NULL;
|
||
|
+ int j = 0;
|
||
|
+
|
||
|
+ if (!adp || !dio) {
|
||
|
+ BCMLOG_ERR("Invalid arg \n");
|
||
|
+ return BC_STS_INV_ARG;
|
||
|
+ }
|
||
|
+
|
||
|
+ if ((dio->page_cnt > 0) && (dio->sig != crystalhd_dio_inv)) {
|
||
|
+ for (j = 0; j < dio->page_cnt; j++) {
|
||
|
+ page = dio->pages[j];
|
||
|
+ if (page) {
|
||
|
+ if (!PageReserved(page) &&
|
||
|
+ (dio->direction == DMA_FROM_DEVICE))
|
||
|
+ SetPageDirty(page);
|
||
|
+ page_cache_release(page);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ if (dio->sig == crystalhd_dio_sg_mapped)
|
||
|
+ pci_unmap_sg(adp->pdev, dio->sg, dio->page_cnt, dio->direction);
|
||
|
+
|
||
|
+ crystalhd_free_dio(adp, dio);
|
||
|
+
|
||
|
+ return BC_STS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_create_dio_pool - Allocate mem pool for DIO management.
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @max_pages: Max pages for size calculation.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * system error.
|
||
|
+ *
|
||
|
+ * This routine creates a memory pool to hold dio context for
|
||
|
+ * for HW Direct IO operation.
|
||
|
+ */
|
||
|
+int crystalhd_create_dio_pool(struct crystalhd_adp *adp, uint32_t max_pages)
|
||
|
+{
|
||
|
+ uint32_t asz = 0, i = 0;
|
||
|
+ uint8_t *temp;
|
||
|
+ crystalhd_dio_req *dio;
|
||
|
+
|
||
|
+ if (!adp || !max_pages) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Get dma memory for fill byte handling..*/
|
||
|
+ adp->fill_byte_pool = pci_pool_create("crystalhd_fbyte",
|
||
|
+ adp->pdev, 8, 8, 0);
|
||
|
+ if (!adp->fill_byte_pool) {
|
||
|
+ BCMLOG_ERR("failed to create fill byte pool\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Get the max size from user based on 420/422 modes */
|
||
|
+ asz = (sizeof(*dio->pages) * max_pages) +
|
||
|
+ (sizeof(*dio->sg) * max_pages) + sizeof(*dio);
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DBG, "Initializing Dio pool %d %d %x %p\n",
|
||
|
+ BC_LINK_SG_POOL_SZ, max_pages, asz, adp->fill_byte_pool);
|
||
|
+
|
||
|
+ for (i = 0; i < BC_LINK_SG_POOL_SZ; i++) {
|
||
|
+ temp = (uint8_t *)kzalloc(asz, GFP_KERNEL);
|
||
|
+ if ((temp) == NULL) {
|
||
|
+ BCMLOG_ERR("Failed to alloc %d mem\n", asz);
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ dio = (crystalhd_dio_req *)temp;
|
||
|
+ temp += sizeof(*dio);
|
||
|
+ dio->pages = (struct page **)temp;
|
||
|
+ temp += (sizeof(*dio->pages) * max_pages);
|
||
|
+ dio->sg = (struct scatterlist *)temp;
|
||
|
+ dio->max_pages = max_pages;
|
||
|
+ dio->fb_va = pci_pool_alloc(adp->fill_byte_pool, GFP_KERNEL,
|
||
|
+ &dio->fb_pa);
|
||
|
+ if (!dio->fb_va) {
|
||
|
+ BCMLOG_ERR("fill byte alloc failed.\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ crystalhd_free_dio(adp, dio);
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_destroy_dio_pool - Release DIO mem pool.
|
||
|
+ * @adp: Adapter instance
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * none.
|
||
|
+ *
|
||
|
+ * This routine releases dio memory pool during close.
|
||
|
+ */
|
||
|
+void crystalhd_destroy_dio_pool(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ crystalhd_dio_req *dio;
|
||
|
+ int count = 0;
|
||
|
+
|
||
|
+ if (!adp) {
|
||
|
+ BCMLOG_ERR("Invalid Arg!!\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ do {
|
||
|
+ dio = crystalhd_alloc_dio(adp);
|
||
|
+ if (dio) {
|
||
|
+ if (dio->fb_va)
|
||
|
+ pci_pool_free(adp->fill_byte_pool,
|
||
|
+ dio->fb_va, dio->fb_pa);
|
||
|
+ count++;
|
||
|
+ kfree(dio);
|
||
|
+ }
|
||
|
+ } while (dio);
|
||
|
+
|
||
|
+ if (adp->fill_byte_pool) {
|
||
|
+ pci_pool_destroy(adp->fill_byte_pool);
|
||
|
+ adp->fill_byte_pool = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DBG, "Released dio pool %d \n", count);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_create_elem_pool - List element pool creation.
|
||
|
+ * @adp: Adapter instance
|
||
|
+ * @pool_size: Number of elements in the pool.
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * 0 - success, <0 error
|
||
|
+ *
|
||
|
+ * Create general purpose list element pool to hold pending,
|
||
|
+ * and active requests.
|
||
|
+ */
|
||
|
+int crystalhd_create_elem_pool(struct crystalhd_adp *adp, uint32_t pool_size)
|
||
|
+{
|
||
|
+ uint32_t i;
|
||
|
+ crystalhd_elem_t *temp;
|
||
|
+
|
||
|
+ if (!adp || !pool_size)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ for (i = 0; i < pool_size; i++) {
|
||
|
+ temp = kzalloc(sizeof(*temp), GFP_KERNEL);
|
||
|
+ if (!temp) {
|
||
|
+ BCMLOG_ERR("kalloc failed \n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+ crystalhd_free_elem(adp, temp);
|
||
|
+ }
|
||
|
+ BCMLOG(BCMLOG_DBG, "allocated %d elem\n", pool_size);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * crystalhd_delete_elem_pool - List element pool deletion.
|
||
|
+ * @adp: Adapter instance
|
||
|
+ *
|
||
|
+ * Return:
|
||
|
+ * none
|
||
|
+ *
|
||
|
+ * Delete general purpose list element pool.
|
||
|
+ */
|
||
|
+void crystalhd_delete_elem_pool(struct crystalhd_adp *adp)
|
||
|
+{
|
||
|
+ crystalhd_elem_t *temp;
|
||
|
+ int dbg_cnt = 0;
|
||
|
+
|
||
|
+ if (!adp)
|
||
|
+ return;
|
||
|
+
|
||
|
+ do {
|
||
|
+ temp = crystalhd_alloc_elem(adp);
|
||
|
+ if (temp) {
|
||
|
+ kfree(temp);
|
||
|
+ dbg_cnt++;
|
||
|
+ }
|
||
|
+ } while (temp);
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DBG, "released %d elem\n", dbg_cnt);
|
||
|
+}
|
||
|
+
|
||
|
+/*================ Debug support routines.. ================================*/
|
||
|
+void crystalhd_show_buffer(uint32_t off, uint8_t *buff, uint32_t dwcount)
|
||
|
+{
|
||
|
+ uint32_t i, k = 1;
|
||
|
+
|
||
|
+ for (i = 0; i < dwcount; i++) {
|
||
|
+ if (k == 1)
|
||
|
+ BCMLOG(BCMLOG_DATA, "0x%08X : ", off);
|
||
|
+
|
||
|
+ BCMLOG(BCMLOG_DATA, " 0x%08X ", *((uint32_t *)buff));
|
||
|
+
|
||
|
+ buff += sizeof(uint32_t);
|
||
|
+ off += sizeof(uint32_t);
|
||
|
+ k++;
|
||
|
+ if ((i == dwcount - 1) || (k > 4)) {
|
||
|
+ BCMLOG(BCMLOG_DATA, "\n");
|
||
|
+ k = 1;
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
diff --git a/drivers/staging/crystalhd/crystalhd_misc.h b/drivers/staging/crystalhd/crystalhd_misc.h
|
||
|
new file mode 100644
|
||
|
index 0000000..a2aa6ad
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/staging/crystalhd/crystalhd_misc.h
|
||
|
@@ -0,0 +1,229 @@
|
||
|
+/***************************************************************************
|
||
|
+ * Copyright (c) 2005-2009, Broadcom Corporation.
|
||
|
+ *
|
||
|
+ * Name: crystalhd_misc . h
|
||
|
+ *
|
||
|
+ * Description:
|
||
|
+ * BCM70012 Linux driver general purpose routines.
|
||
|
+ * Includes reg/mem read and write routines.
|
||
|
+ *
|
||
|
+ * HISTORY:
|
||
|
+ *
|
||
|
+ **********************************************************************
|
||
|
+ * This file is part of the crystalhd device driver.
|
||
|
+ *
|
||
|
+ * This driver is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, version 2 of the License.
|
||
|
+ *
|
||
|
+ * This driver is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this driver. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ **********************************************************************/
|
||
|
+
|
||
|
+#ifndef _CRYSTALHD_MISC_H_
|
||
|
+#define _CRYSTALHD_MISC_H_
|
||
|
+
|
||
|
+#include <linux/module.h>
|
||
|
+#include <linux/kernel.h>
|
||
|
+#include <linux/errno.h>
|
||
|
+#include <linux/string.h>
|
||
|
+#include <linux/ioctl.h>
|
||
|
+#include <linux/dma-mapping.h>
|
||
|
+#include <linux/version.h>
|
||
|
+#include <linux/sched.h>
|
||
|
+#include <asm/system.h>
|
||
|
+#include "bc_dts_glob_lnx.h"
|
||
|
+
|
||
|
+/* Global log level variable defined in crystal_misc.c file */
|
||
|
+extern uint32_t g_linklog_level;
|
||
|
+
|
||
|
+/* Global element pool for all Queue management.
|
||
|
+ * TX: Active = BC_TX_LIST_CNT, Free = BC_TX_LIST_CNT.
|
||
|
+ * RX: Free = BC_RX_LIST_CNT, Active = 2
|
||
|
+ * FW-CMD: 4
|
||
|
+ */
|
||
|
+#define BC_LINK_ELEM_POOL_SZ ((BC_TX_LIST_CNT * 2) + BC_RX_LIST_CNT + 2 + 4)
|
||
|
+
|
||
|
+/* Driver's IODATA pool count */
|
||
|
+#define CHD_IODATA_POOL_SZ (BC_IOCTL_DATA_POOL_SIZE * BC_LINK_MAX_OPENS)
|
||
|
+
|
||
|
+/* Scatter Gather memory pool size for Tx and Rx */
|
||
|
+#define BC_LINK_SG_POOL_SZ (BC_TX_LIST_CNT + BC_RX_LIST_CNT)
|
||
|
+
|
||
|
+enum _crystalhd_dio_sig {
|
||
|
+ crystalhd_dio_inv = 0,
|
||
|
+ crystalhd_dio_locked,
|
||
|
+ crystalhd_dio_sg_mapped,
|
||
|
+};
|
||
|
+
|
||
|
+struct crystalhd_dio_user_info {
|
||
|
+ void *xfr_buff;
|
||
|
+ uint32_t xfr_len;
|
||
|
+ uint32_t uv_offset;
|
||
|
+ bool dir_tx;
|
||
|
+
|
||
|
+ uint32_t uv_sg_ix;
|
||
|
+ uint32_t uv_sg_off;
|
||
|
+ int comp_sts;
|
||
|
+ int ev_sts;
|
||
|
+ uint32_t y_done_sz;
|
||
|
+ uint32_t uv_done_sz;
|
||
|
+ uint32_t comp_flags;
|
||
|
+ bool b422mode;
|
||
|
+};
|
||
|
+
|
||
|
+typedef struct _crystalhd_dio_req {
|
||
|
+ uint32_t sig;
|
||
|
+ uint32_t max_pages;
|
||
|
+ struct page **pages;
|
||
|
+ struct scatterlist *sg;
|
||
|
+ int sg_cnt;
|
||
|
+ int page_cnt;
|
||
|
+ int direction;
|
||
|
+ struct crystalhd_dio_user_info uinfo;
|
||
|
+ void *fb_va;
|
||
|
+ uint32_t fb_size;
|
||
|
+ dma_addr_t fb_pa;
|
||
|
+ struct _crystalhd_dio_req *next;
|
||
|
+} crystalhd_dio_req;
|
||
|
+
|
||
|
+#define BC_LINK_DIOQ_SIG (0x09223280)
|
||
|
+
|
||
|
+typedef struct _crystalhd_elem_s {
|
||
|
+ struct _crystalhd_elem_s *flink;
|
||
|
+ struct _crystalhd_elem_s *blink;
|
||
|
+ void *data;
|
||
|
+ uint32_t tag;
|
||
|
+} crystalhd_elem_t;
|
||
|
+
|
||
|
+typedef void (*crystalhd_data_free_cb)(void *context, void *data);
|
||
|
+
|
||
|
+typedef struct _crystalhd_dioq_s {
|
||
|
+ uint32_t sig;
|
||
|
+ struct crystalhd_adp *adp;
|
||
|
+ crystalhd_elem_t *head;
|
||
|
+ crystalhd_elem_t *tail;
|
||
|
+ uint32_t count;
|
||
|
+ spinlock_t lock;
|
||
|
+ wait_queue_head_t event;
|
||
|
+ crystalhd_data_free_cb data_rel_cb;
|
||
|
+ void *cb_context;
|
||
|
+} crystalhd_dioq_t;
|
||
|
+
|
||
|
+typedef void (*hw_comp_callback)(crystalhd_dio_req *,
|
||
|
+ wait_queue_head_t *event, BC_STATUS sts);
|
||
|
+
|
||
|
+/*========= Decoder (7412) register access routines.================= */
|
||
|
+uint32_t bc_dec_reg_rd(struct crystalhd_adp *, uint32_t);
|
||
|
+void bc_dec_reg_wr(struct crystalhd_adp *, uint32_t, uint32_t);
|
||
|
+
|
||
|
+/*========= Link (70012) register access routines.. =================*/
|
||
|
+uint32_t crystalhd_reg_rd(struct crystalhd_adp *, uint32_t);
|
||
|
+void crystalhd_reg_wr(struct crystalhd_adp *, uint32_t, uint32_t);
|
||
|
+
|
||
|
+/*========= Decoder (7412) memory access routines..=================*/
|
||
|
+BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t *);
|
||
|
+BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t *);
|
||
|
+
|
||
|
+/*==========Link (70012) PCIe Config access routines.================*/
|
||
|
+BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t *);
|
||
|
+BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t);
|
||
|
+
|
||
|
+/*========= Linux Kernel Interface routines. ======================= */
|
||
|
+void *bc_kern_dma_alloc(struct crystalhd_adp *, uint32_t, dma_addr_t *);
|
||
|
+void bc_kern_dma_free(struct crystalhd_adp *, uint32_t,
|
||
|
+ void *, dma_addr_t);
|
||
|
+#define crystalhd_create_event(_ev) init_waitqueue_head(_ev)
|
||
|
+#define crystalhd_set_event(_ev) wake_up_interruptible(_ev)
|
||
|
+#define crystalhd_wait_on_event(ev, condition, timeout, ret, nosig) \
|
||
|
+do { \
|
||
|
+ DECLARE_WAITQUEUE(entry, current); \
|
||
|
+ unsigned long end = jiffies + ((timeout * HZ) / 1000); \
|
||
|
+ ret = 0; \
|
||
|
+ add_wait_queue(ev, &entry); \
|
||
|
+ for (;;) { \
|
||
|
+ __set_current_state(TASK_INTERRUPTIBLE); \
|
||
|
+ if (condition) { \
|
||
|
+ break; \
|
||
|
+ } \
|
||
|
+ if (time_after_eq(jiffies, end)) { \
|
||
|
+ ret = -EBUSY; \
|
||
|
+ break; \
|
||
|
+ } \
|
||
|
+ schedule_timeout((HZ / 100 > 1) ? HZ / 100 : 1); \
|
||
|
+ if (!nosig && signal_pending(current)) { \
|
||
|
+ ret = -EINTR; \
|
||
|
+ break; \
|
||
|
+ } \
|
||
|
+ } \
|
||
|
+ __set_current_state(TASK_RUNNING); \
|
||
|
+ remove_wait_queue(ev, &entry); \
|
||
|
+} while (0)
|
||
|
+
|
||
|
+/*================ Direct IO mapping routines ==================*/
|
||
|
+extern int crystalhd_create_dio_pool(struct crystalhd_adp *, uint32_t);
|
||
|
+extern void crystalhd_destroy_dio_pool(struct crystalhd_adp *);
|
||
|
+extern BC_STATUS crystalhd_map_dio(struct crystalhd_adp *, void *, uint32_t,
|
||
|
+ uint32_t, bool, bool, crystalhd_dio_req**);
|
||
|
+
|
||
|
+extern BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *, crystalhd_dio_req*);
|
||
|
+#define crystalhd_get_sgle_paddr(_dio, _ix) (cpu_to_le64(sg_dma_address(&_dio->sg[_ix])))
|
||
|
+#define crystalhd_get_sgle_len(_dio, _ix) (cpu_to_le32(sg_dma_len(&_dio->sg[_ix])))
|
||
|
+
|
||
|
+/*================ General Purpose Queues ==================*/
|
||
|
+extern BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *, crystalhd_dioq_t **, crystalhd_data_free_cb , void *);
|
||
|
+extern void crystalhd_delete_dioq(struct crystalhd_adp *, crystalhd_dioq_t *);
|
||
|
+extern BC_STATUS crystalhd_dioq_add(crystalhd_dioq_t *ioq, void *data, bool wake, uint32_t tag);
|
||
|
+extern void *crystalhd_dioq_fetch(crystalhd_dioq_t *ioq);
|
||
|
+extern void *crystalhd_dioq_find_and_fetch(crystalhd_dioq_t *ioq, uint32_t tag);
|
||
|
+extern void *crystalhd_dioq_fetch_wait(crystalhd_dioq_t *ioq, uint32_t to_secs, uint32_t *sig_pend);
|
||
|
+
|
||
|
+#define crystalhd_dioq_count(_ioq) ((_ioq) ? _ioq->count : 0)
|
||
|
+
|
||
|
+extern int crystalhd_create_elem_pool(struct crystalhd_adp *, uint32_t);
|
||
|
+extern void crystalhd_delete_elem_pool(struct crystalhd_adp *);
|
||
|
+
|
||
|
+
|
||
|
+/*================ Debug routines/macros .. ================================*/
|
||
|
+extern void crystalhd_show_buffer(uint32_t off, uint8_t *buff, uint32_t dwcount);
|
||
|
+
|
||
|
+enum _chd_log_levels {
|
||
|
+ BCMLOG_ERROR = 0x80000000, /* Don't disable this option */
|
||
|
+ BCMLOG_DATA = 0x40000000, /* Data, enable by default */
|
||
|
+ BCMLOG_SPINLOCK = 0x20000000, /* Spcial case for Spin locks*/
|
||
|
+
|
||
|
+ /* Following are allowed only in debug mode */
|
||
|
+ BCMLOG_INFO = 0x00000001, /* Generic informational */
|
||
|
+ BCMLOG_DBG = 0x00000002, /* First level Debug info */
|
||
|
+ BCMLOG_SSTEP = 0x00000004, /* Stepping information */
|
||
|
+ BCMLOG_ENTER_LEAVE = 0x00000008, /* stack tracking */
|
||
|
+};
|
||
|
+
|
||
|
+#define BCMLOG_ENTER \
|
||
|
+if (g_linklog_level & BCMLOG_ENTER_LEAVE) { \
|
||
|
+ printk("Entered %s\n", __func__); \
|
||
|
+}
|
||
|
+
|
||
|
+#define BCMLOG_LEAVE \
|
||
|
+if (g_linklog_level & BCMLOG_ENTER_LEAVE) { \
|
||
|
+ printk("Leaving %s\n", __func__); \
|
||
|
+}
|
||
|
+
|
||
|
+#define BCMLOG(trace, fmt, args...) \
|
||
|
+if (g_linklog_level & trace) { \
|
||
|
+ printk(fmt, ##args); \
|
||
|
+}
|
||
|
+
|
||
|
+#define BCMLOG_ERR(fmt, args...) \
|
||
|
+do { \
|
||
|
+ if (g_linklog_level & BCMLOG_ERROR) { \
|
||
|
+ printk("*ERR*:%s:%d: "fmt, __FILE__, __LINE__, ##args); \
|
||
|
+ } \
|
||
|
+} while (0);
|
||
|
+
|
||
|
+#endif
|