summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/frontends/dib3000-common.c
blob: 7974fa62369b6a9a67373cdf3189eb102ce22760 (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
#include "dib3000-common.h"

#ifdef CONFIG_DVB_DIBCOM_DEBUG
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
#endif
#define deb_info(args...) dprintk(0x01,args)
#define deb_i2c(args...) dprintk(0x02,args)
#define deb_srch(args...) dprintk(0x04,args)


int dib3000_read_reg(struct dib3000_state *state, u16 reg)
{
	u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
	u8 rb[2];
	struct i2c_msg msg[] = {
		{ .addr = state->config.demod_address, .flags = 0,        .buf = wb, .len = 2 },
		{ .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
	};
	
	if (i2c_transfer(state->i2c, msg, 2) != 2)
		deb_i2c("i2c read error\n");
	
	deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
			(rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);

	return (rb[0] << 8) | rb[1];
}

int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
{
	u8 b[] = {
		(reg >> 8) & 0xff, reg & 0xff,
		(val >> 8) & 0xff, val & 0xff,
	};
	struct i2c_msg msg[] = { 
		{ .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 } 
	};
	deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);

	return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
}

int dib3000_init_pid_list(struct dib3000_state *state, int num)
{
	int i;
	if (state != NULL) {
		state->pid_list = kmalloc(sizeof(struct dib3000_pid) * num,GFP_KERNEL);
		if (state->pid_list == NULL)
			return -ENOMEM;

		deb_info("initializing %d pids for the pid_list.\n",num);
		state->pid_list_lock = SPIN_LOCK_UNLOCKED;
		memset(state->pid_list,0,num*(sizeof(struct dib3000_pid)));
		for (i=0; i < num; i++) {
			state->pid_list[i].pid = 0;
			state->pid_list[i].active = 0;
		}
		state->feedcount = 0;
	} else
		return -EINVAL;

	return 0;
}

void dib3000_dealloc_pid_list(struct dib3000_state *state)
{
	if (state != NULL && state->pid_list != NULL)
		kfree(state->pid_list);
}

/* fetch a pid from pid_list */
int dib3000_get_pid_index(struct dib3000_pid pid_list[], int num_pids, int pid,
		spinlock_t *pid_list_lock,int onoff)
{
	int i,ret = -1;
	unsigned long flags;

	spin_lock_irqsave(pid_list_lock,flags);
	for (i=0; i < num_pids; i++)
		if (onoff) {
			if (!pid_list[i].active) {
				pid_list[i].pid = pid;
				pid_list[i].active = 1;
				ret = i;
				break;
			}
		} else {
			if (pid_list[i].active && pid_list[i].pid == pid) {
				pid_list[i].pid = 0;
				pid_list[i].active = 0;
				ret = i;
				break;
			}
		}
	
	deb_info("setting pid: %5d %04x at index %d '%s'\n",pid,pid,ret,onoff ? "on" : "off");
				
	spin_unlock_irqrestore(pid_list_lock,flags);
	return ret;
}

int dib3000_search_status(u16 irq,u16 lock)
{
	if (irq & 0x02) {
		if (lock & 0x01) {
			deb_srch("auto search succeeded\n");
			return 1; // auto search succeeded
		} else {
			deb_srch("auto search not successful\n");
			return 0; // auto search failed
		}
	} else if (irq & 0x01)  {
		deb_srch("auto search failed\n");
		return 0; // auto search failed
	}
	return -1; // try again 
}

/* for auto search */
u16 dib3000_seq[2][2][2] =     /* fft,gua,   inv   */
	{ /* fft */
		{ /* gua */
			{ 0, 1 },                   /*  0   0   { 0,1 } */
			{ 3, 9 },                   /*  0   1   { 0,1 } */
		},
		{
			{ 2, 5 },                   /*  1   0   { 0,1 } */
			{ 6, 11 },                  /*  1   1   { 0,1 } */
		}
	};

MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers");
MODULE_LICENSE("GPL");

EXPORT_SYMBOL(dib3000_seq);

EXPORT_SYMBOL(dib3000_read_reg);
EXPORT_SYMBOL(dib3000_write_reg);
EXPORT_SYMBOL(dib3000_init_pid_list);
EXPORT_SYMBOL(dib3000_dealloc_pid_list);
EXPORT_SYMBOL(dib3000_get_pid_index);
EXPORT_SYMBOL(dib3000_search_status);