summaryrefslogtreecommitdiff
path: root/polux/devkit/plc-polux/pmd/plc_pmd.h
blob: cc1a631ea704c46ca5ef0cc911eeb47ef95426ee (plain)
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
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
#ifndef __PMD_H_
#define __PMD_H_
/*
 * Copyright (C) 2003 by SPiDCOM Technologies. All rights reserved.
 */

/* Don't merge this */
#include "platform.h"
#include "phlic.h"
#include "pmd.h"

#ifdef USE_OSEDEF_H
#include "osedef.h"
#endif

#define PMD_MAX_SLICES		64	/* FEC status kept for last 64 slices */
#define PMD_PAYLOAD_SIZE	(PMD_SLICE_SIZE*PMD_MAX_SLICES)
#define PMD_DEFAULT_AGCGOAL					0x40

struct pmd_carrier_map {
    uint32_t dword[PMD_MAX_BANDS][(PMD_CARRIERS_PER_BAND + 31) / 32];
};
#define CM_SET(band,carrier,p) \
    ((p)->dword[band][(carrier)/32] |= (1 << ((carrier) % 32)))
#define CM_CLR(band,carrier,p) \
    ((p)->dword[band][(carrier)/32] &= ~(1 << ((carrier) % 32)))
#define CM_ISSET(band,carrier,p) \
((p)->dword[band][(carrier)/32] & (1 << ((carrier) % 32)))
#define CM_ZERO(p)  memset((char *)&((p)->dword), (char) 0, sizeof((p)->dword))
#define CM_ONE(p)  memset((char *)&((p)->dword), (char) 0xff, sizeof((p)->dword))
#define CM_GROUP(band,group,p) (*(((uint8_t*)&((p)->dword[band][0]))+group))

extern int pmd_carrier_dump (char *buf, struct pmd_carrier_map *cs);

extern int pmd_open (int flow);
extern int pmd_start (int flow);

struct pmd_ind {
    void (*rx_start_isr) (int proto, int flow);
    void (*rx_data_isr) (int proto, int flow);
    void (*rx_end_isr) (int proto, int flow);
    void (*tx_data_isr) (int proto, int flow);
    void (*tx_end_isr) (int proto, int flow);
    void (*tx_more_isr) (int proto, int flow);
    void (*busy_isr) (int proto, int flow);
    void (*eof_isr) (int proto, int flow);
    void (*tmo_isr1) (int proto, int flow);
    void (*tmo_isr2) (int proto, int flow);
};

struct pmd_proto {
    int proto;
    struct pmd_ind *ind;
};

int pmd_init (void);

void pmd_cancel_timer1 (void);
void pmd_request_timer1 (int flow, int date);
void pmd_cancel_timer2 (int flow);
void pmd_request_timer2 (int flow, int date);


#define PMD_NB_PROTO	1
#define PMD_PROTO_PLCP	0

#define PMD_NB_FLOW		1

int pmd_register (int proto, struct pmd_ind *ind);

struct pmd_band_quality {
    uint32_t q[2];
};

/* modulation is coded using 4 bits */
#define PMD_BAND_QUALITY_SIZE 	1+((PMD_GROUPS_PER_BAND-1)*4)/8

/* 
 * measured time between tx_last_symbol on sender side 
 * and idle on receiver side is <88 us. Minimum nb_wait is therefore 3
 * (3*36us = 108 us).
 */
#define PMD_WAIT_SLOTS					3

/* constantes concernants les units */
uint16_t PMD_UNIT (int unit);
#define PMD_UNIT_SIZE 0x0100
#define PMD_UNIT_BASE 0x1800

#define PMD_PB_BASE		0x0200
#define PMD_PB_BASE_ADDR	(PMD_PHLIC_DATA_REGBASE+PMD_PB_BASE)



#define pmd_get_nextstate 	pmd_get_current_state
#define pmd_get_val_timer 	pmd_get_timer_value
#define pmd_get_symbolnb  	pmd_get_symbol_nb_phlic
#define pmd_get_next_rx_symbol 	pmd_get_current_rx_symbol
#define pmd_state_idle		pmd_state_state_idle



#define PMD_BAND_SIZE             0x0100
#define PMD_BAND_BASE             0x1000
#define PMD_BAND_NOISE            0x0080
#define PMD_BAND_RX_QUALITY       0x0040
#define PMD_BAND_TX_QUALITY       0x0020

/* adresse de base des données bande */
#define PMD_BAND(band) (PMD_BAND_BASE+PMD_BAND_SIZE*band)


/* données de contrôle */
uint16_t PMD_CTRL (int bands);
uint16_t PMD_TXCTRL (int bands);
uint16_t PMD_RXCTRL (int bands);

#define PMD_CTRL_BASE			  0x1800
#define PMD_TXCTRL_BASE			  0x1820
#define PMD_RXCTRL_BASE			  0x1840
#define PMD_CTRL_SIZE			  0x100

#define pmd_get_agc_gain() (*(uint16_t*)PMD_AGC_CUR_GAIN_ADDR)

#define pmd_set_fixed_agc(gain) {	\
    *(uint16_t*)PMD_AGC_FIXED_GAIN_ADDR = gain; \
    *(uint16_t*)PMD_AGC_MODE_ADDR = PMD_AGC_MODE_FIXED; \
}

#define pmd_get_min_corr(band) \
    *(uint16_t*)(PMD_SAFE_REGBASE + PMD_SAFE_MIN_CORR + band * 2);

#define pmd_get_max_corr(band) \
    *(uint16_t*)(PMD_SAFE_REGBASE + PMD_SAFE_MAX_CORR + band * 2);


#define pmd_freeze_agc() 	\
    *(uint16_t*)PMD_AGC_MODE_ADDR = PMD_AGC_MODE_FROZEN;

#define pmd_set_auto_agc() 	\
    *(uint16_t*)PMD_AGC_MODE_ADDR = PMD_AGC_MODE_AUTO

#define pmd_set_tx_gain(gain)	\
    *(uint16_t*)DSP_OGAIN_ADDR = (uint16_t)(gain)

#define pmd_set_tx_slices_interval(n) \
    *(uint16_t*)(PMD_PHLIC_DATA_REGBASE+0x003C)=(uint16_t)(n)

#define pmd_set_bug_128_position(n) \
    *(uint16_t*)(PMD_PHLIC_DATA_REGBASE+0x18A0)=(uint16_t)(n)

#if defined(CONFIG_TINA_C) || defined(SP_LISA) || defined(CONFIG_ARCH_MSE500)
#define pmd_set_tx_delay(delay)	\
    *(uint16_t*)DSP_TX_ENABLE_DELAY = (uint16_t)(delay)

#define pmd_set_start_detect_level(level)	\
    *(uint16_t*)DSP_START_DETECTION_LEVEL = (uint16_t)(level)
#endif

#define pmd_set_control_mod(mod) \
    *(uint16_t*)PMD_CTRL_MODULATION = (uint16_t)(mod)

#define pmd_rx_control(band)	\
    (PMD_PHLIC_DATA_REGBASE+PMD_RXCTRL_BASE+(band)*PMD_BAND_SIZE)

#define pmd_tx_control(band)	\
    (PMD_PHLIC_DATA_REGBASE+PMD_TXCTRL_BASE+(band)*PMD_BAND_SIZE)

#if defined(CONFIG_TINA_C) || defined(SP_LISA) || defined(CONFIG_ARCH_MSE500)
#define pmd_enable_detection() \
    *(uint16_t*)DSP_START_DETECTION_LEVEL = 0

#define pmd_disable_detection() \
    *(uint16_t*)DSP_START_DETECTION_LEVEL = 0xFFFF

#define pmd_enable_bands_together() \
    *(uint16_t*)DSP_BANDS_TOGETHER = 1

#define pmd_disable_bands_together() \
    *(uint16_t*)DSP_BANDS_TOGETHER = 0

#define pmd_enable_new_tx_filter() \
    *(uint16_t*)DSP_TX_FILTER_TYPE |= 0x0100

#define pmd_disable_new_tx_filter() \
    *(uint16_t*)DSP_TX_FILTER_TYPE &= 0xFEFF

#define pmd_enable_new_rx_filter() \
    *(uint16_t*)DSP_RX_FILTER_TYPE |= 0x0100

#define pmd_disable_new_rx_filter() \
    *(uint16_t*)DSP_RX_FILTER_TYPE &= 0xFEFF

#define pmd_enable_new_shaker() \
    *(uint16_t*)PMD_NEW_SHAKERS = 1

#define pmd_disable_new_shaker() \
    *(uint16_t*)PMD_NEW_SHAKERS = 0
#endif

#if defined(SP_LISA) || defined(CONFIG_ARCH_MSE500)
#define pmd_set_start_coef(val) \
	*(uint16_t*)DSP_START_COEF = (uint16_t)(val)
#define pmd_get_start_coef() \
	*(uint16_t*)(DSP_START_COEF);

#define pmd_set_start_width(val) \
	*(uint16_t*)DSP_START_WIDTH = (uint16_t)(val)
#define pmd_get_start_width() \
	*(uint16_t*)(DSP_START_WIDTH);
#endif

#define pmd_get_min_corr(band) \
    *(uint16_t*)(PMD_SAFE_REGBASE + PMD_SAFE_MIN_CORR + band * 2);

#define pmd_get_max_corr(band) \
    *(uint16_t*)(PMD_SAFE_REGBASE + PMD_SAFE_MAX_CORR + band * 2);



#define PHLIC_PB_BAND		(PMD_PHLIC_DATA_REGBASE+phlic_data_rx_ahb_band_slice_1)
#define PHLIC_PB_BAND_SIZE 	0x2

#define pmd_get_slice_band(n)	\
    (((*(uint16_t*)(PHLIC_PB_BAND+n*PHLIC_PB_BAND_SIZE))-0x1000)>>8)


/* constantes concernant la mémoire d'instruction du phlic */
#define PMD_NO_FLOW                0x0200
#define PMD_FLOW_BASE              0x1000
#define PMD_FLOW_SIZE              0x1000
uint16_t PMD_FLOW (int flow);

#define PMD_GOTO_BASE              0x0008
#define PMD_GOTO_SIZE              0x0040
uint16_t PMD_GOTO (int band);

/* constantes pour DESYR */
#define PMD_DESYR_LINK_BASE        0x0c00
#define PMD_DESYR_LINK_SIZE        0x0010
uint16_t PMD_DESYR_LINK (int band);


/* constantes pour FEC */
#define PMD_FEC_MEM_NB_SLICES      16   // 16 slices for fec debug memory

/* constantes pour SAFE */
#define PMD_SAFE_REAL				0xa000
#define PMD_SAFE_IMAG				0xc000
#define PMD_SAFE_FFT_GAIN			0x9000
#define PMD_SAFE_SETUP				0x1000
#define PMD_SAFE_MIN_CORR			0x8100
#define PMD_SAFE_MAX_CORR			0x8200


/* copie 16 bits vers les virtex */
void copy16 (void *d, void *s, int len /* in bytes */ );

/* desactivation de l'interruption PLC */
void pmd_enable_irq (void);
void pmd_disable_irq (void);

/* noise */
uint16_t pmd_get_noise (int band, int group);

/* modulation */
int pmd_get_mod_bits_per_slot (int mod);

/* processus d'interrutpion */
/*extern void pmd_dma_isr(void);*/
/*extern void pmd_phlic_isr(void);*/
/*extern void ahb_error_isr(void);*/

struct plc_drv_unit;

extern uint16_t pmd_get_time (int flow);
extern void pmd_link_dsp_bands (uint16_t chmr);
extern int pmd_link_phlic_bands (uint16_t chmr);
extern void pmd_unlink_dsp_bands (void);
extern void pmd_set_band (int unit, int band, bool used);
extern void pmd_set_rx_band_nb_slots (int band, int nb_slots);
extern int16_t *pmd_get_safe_real (int band);
extern int16_t *pmd_get_safe_imag (int band);
extern uint16_t pmd_get_fft_gain (int band);
extern uint8_t pmd_get_group_notchs (int band, int group);
extern void pmd_set_group_notchs (int band, int group, uint8_t notchs);
extern bool pmd_is_band_busy (int band);

extern void pmd_set_control_adapt (int band, int carrier, uint16_t value);
extern uint16_t pmd_get_control_adapt (int band, int carrier);
extern void pmd_restore_adapts (void);
extern uint16_t pmd_get_adapt (int band, int carrier);
extern void pmd_set_adapt (int band, int carrier, uint16_t value);
extern void pmd_set_adapt_flat_banana (void);
extern float pmd_get_carrier_frequency (int band, int carrier);
extern void pmd_switch_off_carrier (int band, int carrier);
extern void pmd_switch_on_carrier (int band, int carrier);
extern void pmd_set_aspro_pilots (uint16_t pilots[PMD_MAX_BANDS][2]);
extern void pmd_set_dsp_pilots (uint16_t pilots[PMD_MAX_BANDS][2]);
extern void pmd_get_dsp_pilots (int band, uint16_t * pil1, uint16_t * pil2);

extern void pmd_set_notches (struct pmd_carrier_map *cs);
extern void pmd_set_agc_goal (uint16_t value);

extern void pmd_set_band_adapt (int band, uint16_t value);

void pmd_enable_mod (int band, int mod);
void pmd_disable_mod (int band, int mod);

void pmd_set_tx_filter_gain (uint16_t gain);
void pmd_set_rx_filter_gain (uint16_t gain);

extern void init_tx_gain(int tx_gain);

#define pmd_desyr_link_addr(band)	\
    (PMD_DESYR_REGBASE+PMD_DESYR_LINK_BASE+(int)(band)*PMD_DESYR_LINK_SIZE)

#define pmd_link_dsp_band(slave_band, master_band) \
    *(uint16_t*)(pmd_desyr_link_addr(slave_band)) = master_band;

#define pmd_unlink_dsp_band(band) \
    *(uint16_t*)(pmd_desyr_link_addr(band)) = 0;

/* 2004-12-07 / TF / Change base from 0x1000 to 0x200 
 * Bands shall be configured with values 0x300, 0x400, ... 
 * instead of 0x1100, 0x1200, ... */
#define pmd_set_phlic_band(band) \
    *(uint16_t*)(PMD_PHLIC_CODE_REGBASE+PMD_GOTO_BASE+band*PMD_GOTO_SIZE) = (0x200+(band)*0x100);

#define pmd_unset_phlic_band(band) \
    *(uint16_t*)(PMD_PHLIC_CODE_REGBASE+PMD_GOTO_BASE+band*PMD_GOTO_SIZE) = 0x200;

#define pmd_set_efr(band, efr) \
    *(uint16_t*)(PMD_BANDS_REGBASE+(band)*PMD_BAND_OFFSET) = (uint16_t)(efr)







#define NOP					0x00000000

#define pmd_get_counter	pmd_get_symbol_nb_phlic

#define pmd_band_started(band)	\
    (*(uint16_t*)(PMD_PHLIC_DATA_REGBASE + phlic_data_rx_start_band1 + (band-1)*0x100)!=0)

#define pmd_set_patch_only_start_off() { \
    *(uint32_t*)(PMD_PHLIC_CODE_REGBASE+phlic_code_patch_only_start) = NOP;\
}

#define pmd_set_patch_only_start_on() { \
    *(uint32_t*)(PMD_PHLIC_CODE_REGBASE+phlic_code_patch_only_start) = (0x50000000 + phlic_code_state_idle_preparation); /*goto @state_idle_preparation*/\
}


/* memory mapping for Virtex1 */
/* debug registers for Virtex2 */
struct plc_v2_debug_regs {
    volatile uint16_t pad_00;     /* 00 */
    volatile uint16_t dsp_flbr;   /* 02 */
    volatile uint16_t dsp_clbr;   /* 04 */
    volatile uint16_t pad_06;     /* 06 */
    volatile uint16_t dsp_albr;   /* 08 */
    volatile uint16_t pad_0a[3];  /* 0a-0e */
    volatile uint16_t pad_10[8];  /* 10-1e */
    volatile uint16_t dsp_rbyr;   /* 20 */
    volatile uint16_t pad_22[7];  /* 22-2e */
    volatile uint16_t pad_30[8];  /* 30-3e */
    volatile uint16_t dsp_ibyr;   /* 40 */
};


/* setup registers for Virtex2 */
struct plc_v2_setup_regs {
    volatile uint16_t pad_00;     /* 00 */
    volatile uint16_t dsp_str;    /* 02 (unused) */
    volatile uint16_t dsp_srr;    /* 04 (former dsp_ftr) */
    volatile uint16_t pad_06;     /* 06 */
    volatile uint16_t dsp_mor;    /* 08 */
    volatile uint16_t pad_0a[3];  /* 0a-0e */
    volatile uint16_t dsp_rpr;    /* 10 */
    volatile uint16_t pad_12[7];  /* 12-1e */
    volatile uint16_t dsp_rsr;    /* 20 */
    volatile uint16_t pad_22[7];  /* 22-2e */
    volatile uint16_t pad_30[8];  /* 30-3e */
    volatile uint16_t dsp_ogain;  /* 40 */
    volatile uint16_t pad_42[7];  /* 42-4e */
    volatile uint16_t pad_50[8];  /* 50-5e */
    volatile uint16_t pad_60[8];  /* 60-6e */
    volatile uint16_t pad_70[8];  /* 70-7e */
    volatile uint16_t agc_enable; /* 80 */
    volatile uint16_t agc_fixed_gain;   /* 82 */
    volatile uint16_t agc_detection_period; /* 84 */
    volatile uint16_t agc_correction_period;    /* 86 */
    volatile uint16_t agc_target_amplitude; /* 88 */
    volatile uint16_t agc_threshold;    /* 8a */
    volatile uint16_t agc_multiplier;   /* 8c */
    volatile uint16_t agc_max_gain; /* 8e */
    volatile uint16_t agc_max_pwm;  /* 90 */
    volatile uint16_t agc_current_gain; /* 92 */
    volatile uint16_t agc_zeroes_after_adc_ovr; /* 94 */
    volatile uint16_t tx_enable_delay;  /* 96 */
    volatile uint16_t tx_coding;  /* 98 */
    volatile uint16_t rx_coding;  /* 9a */
    volatile uint16_t pad_9c[2];  /* 9c-9e */
    volatile uint16_t pad_a0[8];  /* a0-ae */
    volatile uint16_t pad_b0[8];  /* b0-be */
    volatile uint16_t pad_c0[8];  /* c0-ce */
    volatile uint16_t pad_d0[8];  /* d0-de */
    volatile uint16_t pad_e0[8];  /* e0-ee */
    volatile uint16_t pad_f0[8];  /* f0-fe */
    volatile uint16_t sport_command;    /* 100 */
    volatile uint16_t panache_mode; /* 102 */
    volatile uint16_t gpo;        /* 104 */
    volatile uint16_t pad_106[5]; /* 106-10e */
    volatile uint16_t sport_w_data_byte_0;  /* 110 */
    volatile uint16_t sport_w_data_byte_1;  /* 112 */
    volatile uint16_t sport_w_data_byte_2;  /* 114 */
    volatile uint16_t sport_w_data_byte_3;  /* 116 */
    volatile uint16_t pad_118[4]; /* 118-10e */
    volatile uint16_t sport_r_data_byte_0;  /* 120 */
    volatile uint16_t sport_r_data_byte_1;  /* 122 */
    volatile uint16_t sport_r_data_byte_2;  /* 124 */
    volatile uint16_t sport_r_data_byte_3;  /* 126 */
};


/* automatic gain control registers */
struct plc_agc_regs {
    volatile uint16_t enable;     /* 80 */
    volatile uint16_t fixed_gain; /* 82 */
    volatile uint16_t detection_period; /* 84 */
    volatile uint16_t correction_period;    /* 86 */
    volatile uint16_t target_amplitude; /* 88 */
    volatile uint16_t threshold;  /* 8a */
    volatile uint16_t correction_factor;    /* 8c */
    volatile uint16_t max_gain;   /* 8e */
    volatile uint16_t max_pwm;    /* 90 */
    volatile uint16_t current_gain; /* 92 */
    volatile uint16_t zeroes_after_adc_ovr; /* 94 */
    volatile uint16_t tx_enable_delay;  /* 96 */
    volatile uint16_t tx_coding;  /* 98 */
    volatile uint16_t rx_coding;  /* 9a */
#if defined(SP_LISA) || defined(CONFIG_ARCH_MSE500)
    volatile uint16_t unlock;     /* 9c LISA BB */
    volatile uint16_t attn;       /* 9e LISA BB */
#endif
};

/* analog front end parameters */
struct plc_paf_regs {
    volatile uint16_t sport_command;    /* 1100 */
    volatile uint16_t panache_mode; /* 1102 */
    volatile uint16_t gpo;        /* 1104 */
    volatile uint16_t pad_106[5]; /* 1106-10e */
    volatile uint16_t sport_w_data_byte_0;  /* 1110 */
    volatile uint16_t sport_w_data_byte_1;  /* 1112 */
    volatile uint16_t sport_w_data_byte_2;  /* 1114 */
    volatile uint16_t sport_w_data_byte_3;  /* 1116 */
    volatile uint16_t pad_118[4]; /* 1118-10e */
    volatile uint16_t sport_r_data_byte_0;  /* 1120 */
    volatile uint16_t sport_r_data_byte_1;  /* 1122 */
    volatile uint16_t sport_r_data_byte_2;  /* 1124 */
    volatile uint16_t sport_r_data_byte_3;  /* 1126 */
};

struct pmd_modulation_thr {
    uint16_t bpsk_thr;
    uint16_t qpsk_thr;
    uint16_t qam16_thr[2];
    uint16_t qam64_thr[3];
    uint16_t qam256_thr[4];
};
#define PMD_MOD_THR_SIZE	(11*sizeof(uint16_t))

#define PMD_BPSK_THR	0x8014    //LISA 80 = enable phlic, must be here
#define PMD_QPSK_THR  	0x0f
#define PMD_QAM16_THR0	0x0a
#define PMD_QAM16_THR1	0x05
#define PMD_QAM64_THR0	0x09
#define PMD_QAM64_THR1	0x04
#define PMD_QAM64_THR2	0x02
#define PMD_QAM256_THR0	0x08
#define PMD_QAM256_THR1	0x04
#define PMD_QAM256_THR2	0x02
#define PMD_QAM256_THR3	0x01


extern struct pmd_modulation_thr pmd_all_mod_thr;


void pmd_write_control (int dst, int src, int xor_mask);
void pmd_read_control (int dst, int src, int xor_mask);
/*void pmd_vote_control(int *dst, int *src);*/
void pmd_sample (int flow, uint16_t nextstate);
char *pmd_get_state_name (uint16_t nextstate);


/* set transmit power for bpsk modulation */
static inline void pmd_set_bpsk_level (int band, uint16_t value)
{
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x14) = value;
}

/* set transmit power for bpsk modulation */
static inline void pmd_set_qpsk_level (int band, uint16_t value)
{
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x16) = value;
}

/* set transmit power for qam16 modulation */
static inline void pmd_set_qam16_level (int band, uint16_t val1, uint16_t val2)
{
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x18) = val1;
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x1a) = val2;
}

/* set transmit power for qam64 modulation */
static inline void pmd_set_qam64_level (int band, uint16_t val1, uint16_t val2, uint16_t val3)
{
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x1c) = val1;
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x1e) = val2;
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x20) = val3;
}

/* set transmit power for qam256 modulation */
static inline void pmd_set_qam256_level (int band, uint16_t val1, uint16_t val2, uint16_t val3, uint16_t val4)
{
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x22) = val1;
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x24) = val2;
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x26) = val3;
    *(volatile uint16_t *) (PMD_BANDS_REGBASE + PMD_BAND_OFFSET * band + 0x28) = val4;
}

/* bpsk */
static inline void pmd_disable_bpsk (int band)
{
    pmd_set_bpsk_level (band, 0x8000);  //LISA 80 must stay here
}

static inline void pmd_enable_bpsk (int band)
{
    pmd_set_bpsk_level (band, PMD_BPSK_THR);
}

/* qpsk */
static inline void pmd_disable_qpsk (int band)
{
    pmd_set_qpsk_level (band, 0x0);
}

static inline void pmd_enable_qpsk (int band)
{
    pmd_set_qpsk_level (band, PMD_QPSK_THR);
}

/* qam16 */
static inline void pmd_disable_qam16 (int band)
{
    pmd_set_qam16_level (band, 0x0, 0x0);
}

static inline void pmd_enable_qam16 (int band)
{
    pmd_set_qam16_level (band, PMD_QAM16_THR0, PMD_QAM16_THR1);
}

/* qam64 */
static inline void pmd_disable_qam64 (int band)
{
    pmd_set_qam64_level (band, 0x0, 0x0, 0x0);
}

static inline void pmd_enable_qam64 (int band)
{
    pmd_set_qam64_level (band, PMD_QAM64_THR0, PMD_QAM64_THR1, PMD_QAM64_THR2);
}

/* qam256 */
static inline void pmd_disable_qam256 (int band)
{
    pmd_set_qam256_level (band, 0x0, 0x0, 0x0, 0x0);
}

static inline void pmd_enable_qam256 (int band)
{
    pmd_set_qam256_level (band, PMD_QAM256_THR0, PMD_QAM256_THR1, PMD_QAM256_THR2, PMD_QAM256_THR3);
}

static inline void pmd_enable_all_mod (int band)
{
    pmd_enable_bpsk (band);
    pmd_enable_qpsk (band);
    pmd_enable_qam16 (band);
    pmd_enable_qam64 (band);
    pmd_enable_qam256 (band);
}

static inline void pmd_disable_all_mod (int band)
{
    pmd_disable_bpsk (band);
    pmd_disable_qpsk (band);
    pmd_disable_qam16 (band);
    pmd_disable_qam64 (band);
    pmd_disable_qam256 (band);
}

int pmd_get_bad_bands (int flow);

int pmd_clear_bad_bands (int flow);

static inline void do_pmd_set_chmr (char *file, int line, u16 chmr)
{
    //  rt_printk("%s:%d set_chmr %x\n", file, line, chmr);
    *(volatile u16 *) DSP_CHMR_ADDR = chmr;
}

static inline u16 do_pmd_read_chmr (char *file, int line)
{
    u16 chmr = *(volatile u16 *) DSP_CHMR_ADDR;
    //  rt_printk("%s:%d read_chmr %x\n", file, line, chmr);
    return chmr;
}

#define pmd_set_chmr(chmr)	do_pmd_set_chmr(__FILE__,__LINE__,chmr)
#define pmd_read_chmr()		do_pmd_read_chmr(__FILE__,__LINE__)

#endif                            /* PMD_H */