aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/crystalhd/crystalhd_hw.h
blob: 3efbf9d4ff5d55a3322a33118a76122686f62d4f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
/***************************************************************************
 * 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

union addr_64 {
	struct {
		uint32_t	low_part;
		uint32_t	high_part;
	};

	uint64_t	full_addr;

};

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;

};

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;

};

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;

};

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;

};

union desc_low_addr_reg {
	struct {
		uint32_t	list_valid:1;
		uint32_t	reserved:4;
		uint32_t	low_addr:27;
	};

	uint32_t	whole_reg;

};

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 */

};

/*
 * 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.
 */
struct dma_desc_mem {
	struct dma_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 */

};

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,
};

struct tx_dma_pkt {
	struct dma_desc_mem	desc_mem;
	hw_comp_callback	call_back;
	struct crystalhd_dio_req	*dio_req;
	wait_queue_head_t	*cb_event;
	uint32_t		list_tag;
};

struct crystalhd_rx_dma_pkt {
	struct dma_desc_mem		desc_mem;
	struct crystalhd_dio_req	*dio_req;
	uint32_t			pkt_tag;
	uint32_t			flags;
	struct BC_PIC_INFO_BLOCK	pib;
	dma_addr_t			uv_phy_addr;
	struct crystalhd_rx_dma_pkt	*next;
};

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 {
	struct tx_dma_pkt	tx_pkt_pool[DMA_ENGINE_CNT];
	spinlock_t		lock;

	uint32_t		tx_ioq_tag_seed;
	uint32_t		tx_list_post_index;

	struct 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;

	struct crystalhd_dioq	*tx_freeq;
	struct crystalhd_dioq	*tx_actq;

	/* Rx DMA Engine Specific Locks */
	spinlock_t		rx_lock;
	uint32_t		rx_list_post_index;
	enum list_sts		rx_list_sts[DMA_ENGINE_CNT];
	struct crystalhd_dioq	*rx_rdyq;
	struct crystalhd_dioq	*rx_freeq;
	struct crystalhd_dioq	*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 ****/
enum BC_STATUS crystalhd_download_fw(struct crystalhd_adp *adp,
			      void *buffer, uint32_t sz);
enum BC_STATUS crystalhd_do_fw_cmd(struct crystalhd_hw *hw, struct BC_FW_CMD *fw_cmd);
bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw);
enum BC_STATUS crystalhd_hw_open(struct crystalhd_hw *, struct crystalhd_adp *);
enum BC_STATUS crystalhd_hw_close(struct crystalhd_hw *);
enum BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *);
enum BC_STATUS crystalhd_hw_free_dma_rings(struct crystalhd_hw *);


enum BC_STATUS crystalhd_hw_post_tx(struct crystalhd_hw *hw, struct crystalhd_dio_req *ioreq,
			     hw_comp_callback call_back,
			     wait_queue_head_t *cb_event,
			     uint32_t *list_id, uint8_t data_flags);

enum BC_STATUS crystalhd_hw_pause(struct crystalhd_hw *hw);
enum BC_STATUS crystalhd_hw_unpause(struct crystalhd_hw *hw);
enum BC_STATUS crystalhd_hw_suspend(struct crystalhd_hw *hw);
enum BC_STATUS crystalhd_hw_cancel_tx(struct crystalhd_hw *hw, uint32_t list_id);
enum BC_STATUS crystalhd_hw_add_cap_buffer(struct crystalhd_hw *hw,
				    struct crystalhd_dio_req *ioreq, bool en_post);
enum BC_STATUS crystalhd_hw_get_cap_buffer(struct crystalhd_hw *hw,
				    struct BC_PIC_INFO_BLOCK *pib,
				    struct crystalhd_dio_req **ioreq);
enum BC_STATUS crystalhd_hw_stop_capture(struct crystalhd_hw *hw);
enum 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 */
enum BC_STATUS crystalhd_hw_set_core_clock(struct crystalhd_hw *);

#endif