• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Driver for Sharp s921 driver
3  *
4  * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
5  *
6  * All rights reserved.
7  *
8  */
9 
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/delay.h>
13 #include "dvb_frontend.h"
14 #include "s921_module.h"
15 #include "s921_core.h"
16 
17 static  unsigned int debug = 0;
18 module_param(debug, int, 0644);
19 MODULE_PARM_DESC(debug,"s921 debugging (default off)");
20 
21 #define dprintk(fmt, args...) if (debug) do {\
22 			printk("s921 debug: " fmt, ##args); } while (0)
23 
24 struct s921_state
25 {
26 	struct dvb_frontend frontend;
27 	fe_modulation_t current_modulation;
28 	__u32 snr;
29 	__u32 current_frequency;
30 	__u8 addr;
31 	struct s921_isdb_t dev;
32 	struct i2c_adapter *i2c;
33 };
34 
s921_set_parameters(struct dvb_frontend * fe,struct dvb_frontend_parameters * param)35 static int s921_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
36 	struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
37 	struct s921_isdb_t_transmission_mode_params params;
38 	struct s921_isdb_t_tune_params tune_params;
39 
40 	tune_params.frequency = param->frequency;
41 	s921_isdb_cmd(&state->dev, ISDB_T_CMD_SET_PARAM, &params);
42 	s921_isdb_cmd(&state->dev, ISDB_T_CMD_TUNE, &tune_params);
43 	mdelay(100);
44 	return 0;
45 }
46 
s921_init(struct dvb_frontend * fe)47 static int s921_init(struct dvb_frontend *fe) {
48 	printk("s921 init\n");
49 	return 0;
50 }
51 
s921_sleep(struct dvb_frontend * fe)52 static int s921_sleep(struct dvb_frontend *fe) {
53 	printk("s921 sleep\n");
54 	return 0;
55 }
56 
s921_read_status(struct dvb_frontend * fe,fe_status_t * status)57 static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
58 {
59 	struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
60 	unsigned int ret;
61 	mdelay(5);
62 	s921_isdb_cmd(&state->dev, ISDB_T_CMD_GET_STATUS, &ret);
63 	*status = 0;
64 
65 	printk("status: %02x\n", ret);
66 	if (ret == 1) {
67 		*status |= FE_HAS_CARRIER;
68 		*status |= FE_HAS_VITERBI;
69 		*status |= FE_HAS_LOCK;
70 		*status |= FE_HAS_SYNC;
71 		*status |= FE_HAS_SIGNAL;
72 	}
73 
74 	return 0;
75 }
76 
s921_read_ber(struct dvb_frontend * fe,__u32 * ber)77 static int s921_read_ber(struct dvb_frontend *fe, __u32 *ber)
78 {
79 	dprintk("read ber\n");
80 	return 0;
81 }
82 
s921_read_snr(struct dvb_frontend * fe,__u16 * snr)83 static int s921_read_snr(struct dvb_frontend *fe, __u16 *snr)
84 {
85 	dprintk("read snr\n");
86 	return 0;
87 }
88 
s921_read_ucblocks(struct dvb_frontend * fe,__u32 * ucblocks)89 static int s921_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
90 {
91 	dprintk("read ucblocks\n");
92 	return 0;
93 }
94 
s921_release(struct dvb_frontend * fe)95 static void s921_release(struct dvb_frontend *fe)
96 {
97 	struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
98 	kfree(state);
99 }
100 
101 static struct dvb_frontend_ops demod_s921={
102 	.info = {
103 		.name			= "SHARP S921",
104 		.type			= FE_OFDM,
105 		.frequency_min		= 473143000,
106 		.frequency_max		= 767143000,
107 		.frequency_stepsize	=   6000000,
108 		.frequency_tolerance	= 0,
109 		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
110 			FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
111 			FE_CAN_FEC_AUTO |
112 			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
113 			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
114 			FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
115 			FE_CAN_MUTE_TS
116 	},
117 	.init = s921_init,
118 	.sleep = s921_sleep,
119 	.set_frontend = s921_set_parameters,
120 	.read_snr = s921_read_snr,
121 	.read_ber = s921_read_ber,
122 	.read_status = s921_read_status,
123 	.read_ucblocks = s921_read_ucblocks,
124 	.release = s921_release,
125 };
126 
s921_write(void * dev,u8 reg,u8 val)127 static int s921_write(void *dev, u8 reg, u8 val) {
128 	struct s921_state *state = dev;
129 	char buf[2]={reg,val};
130 	int err;
131 	struct i2c_msg i2cmsgs = {
132 		.addr = state->addr,
133 		.flags = 0,
134 		.len = 2,
135 		.buf = buf
136 	};
137 
138 	if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
139 		printk("%s i2c_transfer error %d\n", __func__, err);
140 		if (err < 0)
141 			return err;
142 		else
143 			return -EREMOTEIO;
144 	}
145 
146 	return 0;
147 }
148 
s921_read(void * dev,u8 reg)149 static int s921_read(void *dev, u8 reg) {
150 	struct s921_state *state = dev;
151 	u8 b1;
152 	int ret;
153 	struct i2c_msg msg[2] = { { .addr = state->addr,
154 				    .flags = 0,
155 				    .buf = &reg, .len = 1 },
156 				  { .addr = state->addr,
157 				    .flags = I2C_M_RD,
158 				    .buf = &b1, .len = 1 } };
159 
160 	ret = i2c_transfer(state->i2c, msg, 2);
161 	if (ret != 2)
162 		return ret;
163 	return b1;
164 }
165 
s921_attach(const struct s921_config * config,struct i2c_adapter * i2c)166 struct dvb_frontend* s921_attach(const struct s921_config *config,
167 					   struct i2c_adapter *i2c)
168 {
169 
170 	struct s921_state *state;
171 	state = kzalloc(sizeof(struct s921_state), GFP_KERNEL);
172 	memset(state, 0x0, sizeof(struct s921_state));
173 
174 	state->addr = config->i2c_address;
175 	state->i2c = i2c;
176 	state->dev.i2c_write = &s921_write;
177 	state->dev.i2c_read = &s921_read;
178 	state->dev.priv_dev = state;
179 
180 	s921_isdb_cmd(&state->dev, ISDB_T_CMD_INIT, NULL);
181 
182 	memcpy(&state->frontend.ops, &demod_s921, sizeof(struct dvb_frontend_ops));
183 	state->frontend.demodulator_priv = state;
184 	return &state->frontend;
185 }
186 
187 EXPORT_SYMBOL_GPL(s921_attach);
188 MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>");
189 MODULE_DESCRIPTION("Sharp S921 ISDB-T 1Seg");
190 MODULE_LICENSE("GPL");
191