aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/tuner-xc2028-types.h99
-rw-r--r--drivers/media/video/tuner-xc2028.c452
-rw-r--r--drivers/media/video/tuner-xc2028.h15
3 files changed, 455 insertions, 111 deletions
diff --git a/drivers/media/video/tuner-xc2028-types.h b/drivers/media/video/tuner-xc2028-types.h
new file mode 100644
index 000000000000..80b19eb1b083
--- /dev/null
+++ b/drivers/media/video/tuner-xc2028-types.h
@@ -0,0 +1,99 @@
1/* tuner-xc2028_types
2 *
3 * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
4 * This code is placed under the terms of the GNU General Public License v2
5 */
6
7/* xc3028 firmware types */
8
9/* BASE firmware should be loaded before any other firmware */
10#define BASE (1<<0)
11
12/* F8MHZ marks BASE firmwares for 8 MHz Bandwidth */
13#define F8MHZ (1<<1)
14
15/* Multichannel Television Sound (MTS)
16 Those firmwares are capable of using xc2038 DSP to decode audio and
17 produce a baseband audio output on some pins of the chip.
18 There are MTS firmwares for the most used video standards. It should be
19 required to use MTS firmwares, depending on the way audio is routed into
20 the bridge chip
21 */
22#define MTS (1<<2)
23
24/* FIXME: I have no idea what's the difference between
25 D2620 and D2633 firmwares
26 */
27#define D2620 (1<<3)
28#define D2633 (1<<4)
29
30/* DTV firmwares for 6, 7 and 8 MHz
31 DTV6 - 6MHz - ATSC/DVB-C/DVB-T/ISDB-T/DOCSIS
32 DTV8 - 8MHz - DVB-C/DVB-T
33 */
34#define DTV6_ATSC (1<<5)
35#define DTV6_QAM (1<<6)
36#define DTV7 (1<<7)
37#define DTV78 (1<<8)
38#define DTV8 (1<<9)
39
40/* There's a FM | BASE firmware + FM specific firmware (std=0) */
41#define FM (1<<10)
42
43/* Applies only for FM firmware
44 Makes it use RF input 1 (pin #2) instead of input 2 (pin #4)
45 */
46#define INPUT1 (1<<11)
47
48
49/* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
50 and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
51 There are variants both with and without NOGD
52 */
53#define LCD (1<<12)
54
55/* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
56 and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
57 */
58#define NOGD (1<<13)
59
60/* Old firmwares were broken into init0 and init1 */
61#define INIT1 (1<<14)
62
63/* Newer types to be moved to videodev2.h */
64
65#define V4L2_STD_SECAM_K3 (0x02000000)
66
67/* Audio types */
68
69#define V4L2_STD_A2_A (1L<<32)
70#define V4L2_STD_A2_B (1L<<33)
71#define V4L2_STD_NICAM_A (1L<<34)
72#define V4L2_STD_NICAM_B (1L<<35)
73#define V4L2_STD_AM (1L<<36)
74#define V4L2_STD_BTSC (1L<<37)
75#define V4L2_STD__EIAJ (1L<<38)
76
77#define V4L2_STD_A2 (V4L2_STD_A2_A | V4L2_STD_A2_B)
78#define V4L2_STD_NICAM (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B)
79
80/* To preserve backward compatibilty,
81 (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported
82 */
83
84#define V4L2_STD_AUDIO (V4L2_STD_A2 | \
85 V4L2_STD_NICAM | \
86 V4L2_STD_AM | \
87 V4L2_STD_BTSC | \
88 V4L2_STD_EIAJ)
89
90/* Used standards with audio restrictions */
91
92#define V4L2_STD_PAL_BG_A2_A (V4L2_STD_PAL_BG | V4L2_STD_A2_A)
93#define V4L2_STD_PAL_BG_A2_B (V4L2_STD_PAL_BG | V4L2_STD_A2_B)
94#define V4L2_STD_PAL_BG_NICAM_A (V4L2_STD_PAL_BG | V4L2_STD_NICAM_A)
95#define V4L2_STD_PAL_BG_NICAM_B (V4L2_STD_PAL_BG | V4L2_STD_NICAM_B)
96#define V4L2_STD_PAL_DK_A2 (V4L2_STD_PAL_DK | V4L2_STD_A2)
97#define V4L2_STD_PAL_DK_NICAM (V4L2_STD_PAL_DK | V4L2_STD_NICAM)
98#define V4L2_STD_SECAM_L_NICAM (V4L2_STD_SECAM_L | V4L2_STD_NICAM)
99#define V4L2_STD_SECAM_L_AM (V4L2_STD_SECAM_L | V4L2_STD_AM)
diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
index e4c371896de4..7d53d58aafa1 100644
--- a/drivers/media/video/tuner-xc2028.c
+++ b/drivers/media/video/tuner-xc2028.c
@@ -15,6 +15,7 @@
15#include <linux/mutex.h> 15#include <linux/mutex.h>
16#include "tuner-i2c.h" 16#include "tuner-i2c.h"
17#include "tuner-xc2028.h" 17#include "tuner-xc2028.h"
18#include "tuner-xc2028-types.h"
18 19
19#include <linux/dvb/frontend.h> 20#include <linux/dvb/frontend.h>
20#include "dvb_frontend.h" 21#include "dvb_frontend.h"
@@ -22,21 +23,13 @@
22#define PREFIX "xc2028 " 23#define PREFIX "xc2028 "
23 24
24static LIST_HEAD(xc2028_list); 25static LIST_HEAD(xc2028_list);
25 26/* struct for storing firmware table */
26/* Firmwares used on tm5600/tm6000 + xc2028/xc3028 */ 27struct firmware_description {
27 28 unsigned int type;
28/* Generic firmwares */ 29 v4l2_std_id id;
29static const char *firmware_INIT0 = "tm_xc3028_MTS_init0.fw"; 30 unsigned char *ptr;
30static const char *firmware_8MHZ_INIT0 = "tm_xc3028_8M_MTS_init0.fw"; 31 unsigned int size;
31static const char *firmware_INIT1 = "tm_xc3028_68M_MTS_init1.fw"; 32};
32
33/* Standard-specific firmwares */
34static const char *firmware_6M = "tm_xc3028_DTV_6M.fw";
35static const char *firmware_7M = "tm_xc3028_DTV_7M.fw";
36static const char *firmware_8M = "tm_xc3028_DTV_8M.fw";
37static const char *firmware_B = "tm_xc3028_B_PAL.fw";
38static const char *firmware_DK = "tm_xc3028_DK_PAL_MTS.fw";
39static const char *firmware_MN = "tm_xc3028_MN_BTSC.fw";
40 33
41struct xc2028_data { 34struct xc2028_data {
42 struct list_head xc2028_list; 35 struct list_head xc2028_list;
@@ -46,7 +39,14 @@ struct xc2028_data {
46 struct device *dev; 39 struct device *dev;
47 void *video_dev; 40 void *video_dev;
48 int count; 41 int count;
49 u32 frequency; 42 __u32 frequency;
43
44 struct firmware_description *firm;
45 int firm_size;
46
47 __u16 version;
48
49 struct xc2028_ctrl ctrl;
50 50
51 v4l2_std_id firm_type; /* video stds supported 51 v4l2_std_id firm_type; /* video stds supported
52 by current firmware */ 52 by current firmware */
@@ -54,6 +54,9 @@ struct xc2028_data {
54 6M, 7M or 8M */ 54 6M, 7M or 8M */
55 int need_load_generic; /* The generic firmware 55 int need_load_generic; /* The generic firmware
56 were loaded? */ 56 were loaded? */
57
58 int max_len; /* Max firmware chunk */
59
57 enum tuner_mode mode; 60 enum tuner_mode mode;
58 struct i2c_client *i2c_client; 61 struct i2c_client *i2c_client;
59 62
@@ -102,92 +105,263 @@ static int xc2028_get_reg(struct xc2028_data *priv, u16 reg)
102 return (buf[1])|(buf[0]<<8); 105 return (buf[1])|(buf[0]<<8);
103} 106}
104 107
105static int load_firmware (struct dvb_frontend *fe, const char *name) 108static void free_firmware (struct xc2028_data *priv)
106{ 109{
107 struct xc2028_data *priv = fe->tuner_priv; 110 int i;
111
112 if (!priv->firm)
113 return;
114
115 for (i=0;i<priv->firm_size;i++) {
116 if (priv->firm[i].ptr)
117 kfree(priv->firm[i].ptr);
118 }
119 kfree(priv->firm);
120
121 priv->firm=NULL;
122 priv->need_load_generic = 1;
123}
124
125static int load_all_firmwares (struct dvb_frontend *fe)
126{
127 struct xc2028_data *priv = fe->tuner_priv;
108 const struct firmware *fw=NULL; 128 const struct firmware *fw=NULL;
109 unsigned char *p, *endp; 129 unsigned char *p, *endp;
110 int len=0, rc=0; 130 int rc=0, n, n_array;
111 static const char firmware_ver[] = "tm6000/xcv v1"; 131 char name[33];
112 132
113 tuner_info("%s called\n", __FUNCTION__); 133 tuner_info("%s called\n", __FUNCTION__);
114 134
115 tuner_info("Loading firmware %s\n", name); 135 tuner_info("Loading firmware %s\n", priv->ctrl.fname);
116 rc = request_firmware(&fw, name, priv->dev); 136 rc = request_firmware(&fw, priv->ctrl.fname, priv->dev);
117 if (rc < 0) { 137 if (rc < 0) {
118 if (rc==-ENOENT) 138 if (rc==-ENOENT)
119 tuner_info("Error: firmware %s not found.\n", name); 139 tuner_info("Error: firmware %s not found.\n",
140 priv->ctrl.fname);
120 else 141 else
121 tuner_info("Error %d while requesting firmware %s \n", rc, name); 142 tuner_info("Error %d while requesting firmware %s \n",
143 rc, priv->ctrl.fname);
122 144
123 return rc; 145 return rc;
124 } 146 }
125 p=fw->data; 147 p=fw->data;
126 endp=p+fw->size; 148 endp=p+fw->size;
127 149
128 if(fw->size==0) { 150 if(fw->size<sizeof(name)-1+2) {
129 tuner_info("Error: firmware size is zero!\n"); 151 tuner_info("Error: firmware size is zero!\n");
130 rc=-EINVAL; 152 rc=-EINVAL;
131 goto err; 153 goto done;
132 } 154 }
133 if (fw->size<sizeof(firmware_ver)-1) { 155
134 /* Firmware is incorrect */ 156 memcpy(name,p,sizeof(name)-1);
135 tuner_info("Error: firmware size is less than header (%d<%d)!\n", 157 name[sizeof(name)-1]=0;
136 (int)fw->size,(int)sizeof(firmware_ver)-1); 158 p+=sizeof(name)-1;
137 rc=-EINVAL; 159
138 goto err; 160 priv->version = le16_to_cpu(*(__u16 *)p);
161 p += 2;
162
163 tuner_info("firmware: %s, ver %d.%d\n", name,
164 priv->version>>8, priv->version&0xff);
165
166 if (p+2>endp)
167 goto corrupt;
168
169 n_array = le16_to_cpu(*(__u16 *)p);
170 p += 2;
171
172 tuner_info("there are %d firmwares at %s\n", n_array, priv->ctrl.fname);
173
174 priv->firm=kzalloc(sizeof(*priv->firm)*n_array,GFP_KERNEL);
175
176 if (!fw) {
177 tuner_info("Not enough memory for loading firmware.\n");
178 rc=-ENOMEM;
179 goto done;
139 } 180 }
140 181
141 if (memcmp(p,firmware_ver,sizeof(firmware_ver)-1)) { 182 priv->firm_size = n_array;
142 /* Firmware is incorrect */ 183 n=-1;
143 tuner_info("Error: firmware is not for tm5600/6000 + Xcv2028/3028!\n"); 184 while (p<endp) {
144 rc=-EINVAL; 185 __u32 type, size;
145 goto err; 186 v4l2_std_id id;
187
188 n++;
189 if (n >= n_array) {
190 tuner_info("Too much firmwares at the file\n");
191 goto corrupt;
192 }
193
194 /* Checks if there's enough bytes to read */
195 if (p+sizeof(type)+sizeof(id)+sizeof(size)>endp) {
196 tuner_info("Lost firmware!\n");
197 goto corrupt;
198 }
199
200 type = le32_to_cpu(*(__u32 *)p);
201 p += sizeof(type);
202
203 id = le64_to_cpu(*(v4l2_std_id *)p);
204 p += sizeof(id);
205
206 size = le32_to_cpu(*(v4l2_std_id *)p);
207 p += sizeof(size);
208
209 if ((!size)||(size+p>endp)) {
210 tuner_info("Firmware type %x, id %lx corrupt\n",
211 type, (unsigned long) id);
212 goto corrupt;
213 }
214
215 priv->firm[n].ptr=kzalloc(size,GFP_KERNEL);
216 if (!priv->firm[n].ptr) {
217 tuner_info("Not enough memory.\n");
218 rc=-ENOMEM;
219 goto err;
220 }
221 tuner_info("Loading firmware type %x, id %lx, size=%d.\n",
222 type, (unsigned long) id, size);
223
224 memcpy(priv->firm[n].ptr, p, size);
225 priv->firm[n].type = type;
226 priv->firm[n].id = id;
227 priv->firm[n].size = size;
228
229 p += size;
230 }
231
232 if (n+1 != priv->firm_size) {
233 tuner_info("Firmware file is incomplete!\n");
234 goto corrupt;
235 }
236
237 goto done;
238
239corrupt:
240 rc=-EINVAL;
241 tuner_info("Error: firmware file is corrupted!\n");
242
243err:
244 tuner_info("Releasing loaded firmware file.\n");
245
246 free_firmware(priv);
247
248done:
249 release_firmware(fw);
250 tuner_info("Firmware files loaded.\n");
251
252 return rc;
253}
254
255static int load_firmware (struct dvb_frontend *fe, unsigned int type,
256 v4l2_std_id *id)
257{
258 struct xc2028_data *priv = fe->tuner_priv;
259 int i, rc;
260 unsigned char *p, *endp, buf[priv->max_len];
261
262 tuner_info("%s called\n", __FUNCTION__);
263
264 if (!priv->firm) {
265 printk (KERN_ERR PREFIX "Error! firmware not loaded\n");
266 return -EINVAL;
267 }
268
269 if ((type == 0) && (*id == 0))
270 *id=V4L2_STD_PAL;
271
272 /* Seek for exact match */
273 for (i=0;i<priv->firm_size;i++) {
274 if ( (type == priv->firm[i].type) &&
275 (*id == priv->firm[i].id))
276 goto found;
277 }
278
279 /* Seek for generic video standard match */
280 for (i=0;i<priv->firm_size;i++) {
281 if ( (type == priv->firm[i].type) && (*id & priv->firm[i].id))
282 goto found;
283 }
284
285 /*FIXME: Would make sense to seek for type "hint" match ? */
286
287 tuner_info ("Can't find firmware for type=%x, id=%lx\n", type,
288 (long int)*id);
289 return -EINVAL;
290
291found:
292 *id = priv->firm[i].id;
293 tuner_info ("Found firmware for type=%x, id=%lx\n", type,
294 (long int)*id);
295
296 p = priv->firm[i].ptr;
297
298 if (!p) {
299 printk(KERN_ERR PREFIX "Firmware pointer were freed!");
300 return -EINVAL;
146 } 301 }
147 p+=sizeof(firmware_ver)-1; 302 endp = p+priv->firm[i].size;
148 303
149 while(p<endp) { 304 while (p<endp) {
150 if ((*p) & 0x80) { 305 __u16 size;
306
307 /* Checks if there's enough bytes to read */
308 if (p+sizeof(size)>endp) {
309 tuner_info("missing bytes\n");
310 return -EINVAL;
311 }
312
313
314 size = le16_to_cpu(*(__u16 *)p);
315 p += sizeof(size);
316
317 if (size == 0xffff)
318 return 0;
319
320 if (!size) {
151 /* Special callback command received */ 321 /* Special callback command received */
152 rc = priv->tuner_callback(priv->video_dev, 322 rc = priv->tuner_callback(priv->video_dev,
153 XC2028_TUNER_RESET, (*p)&0x7f); 323 XC2028_TUNER_RESET, 0);
154 if (rc<0) { 324 if (rc<0) {
155 tuner_info("Error at RESET code %d\n", 325 tuner_info("Error at RESET code %d\n",
156 (*p)&0x7f); 326 (*p)&0x7f);
157 goto err; 327 return -EINVAL;
158 } 328 }
159 p++;
160 continue; 329 continue;
161 } 330 }
162 len=*p; 331
163 p++; 332 /* Checks for a sleep command */
164 if (p+len+1>endp) { 333 if (size & 0x8000) {
165 /* Firmware is incorrect */ 334 msleep (size & 0x7fff);
166 tuner_info("Error: firmware is truncated!\n"); 335 continue;
167 rc=-EINVAL;
168 goto err;
169 }
170 if (len<=0) {
171 tuner_info("Error: firmware file is corrupted!\n");
172 rc=-EINVAL;
173 goto err;
174 } 336 }
175 337
176 i2c_send(rc, priv, p, len); 338 if ((size + p > endp)) {
177 if (rc<0) 339 tuner_info("missing bytes: need %d, have %d\n",
178 goto err; 340 size, (int)(endp-p));
179 p+=len; 341 return -EINVAL;
342 }
180 343
181 if (*p) 344 buf[0] = *p;
182 msleep(*p);
183 p++; 345 p++;
184 } 346 size--;
185 347
348 /* Sends message chunks */
349 while (size>0) {
350 int len = (size<priv->max_len-1)?size:priv->max_len-1;
186 351
187err: 352 memcpy(buf+1, p, len);
188 release_firmware(fw);
189 353
190 return rc; 354 i2c_send(rc, priv, buf, len+1);
355 if (rc<0) {
356 tuner_info("%d returned from send\n",rc);
357 return -EINVAL;
358 }
359
360 p += len;
361 size -= len;
362 }
363 }
364 return -EINVAL;
191} 365}
192 366
193static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode, 367static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
@@ -196,11 +370,21 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
196{ 370{
197 struct xc2028_data *priv = fe->tuner_priv; 371 struct xc2028_data *priv = fe->tuner_priv;
198 int rc, version; 372 int rc, version;
199 const char *name; 373 v4l2_std_id std0=0;
200 int change_digital_bandwidth; 374 unsigned int type0=0,type=0;
375 int change_digital_bandwidth;
201 376
202 tuner_info("%s called\n", __FUNCTION__); 377 tuner_info("%s called\n", __FUNCTION__);
203 378
379 if (!priv->firm) {
380 if (!priv->ctrl.fname)
381 return -EINVAL;
382
383 rc=load_all_firmwares(fe);
384 if (rc<0)
385 return rc;
386 }
387
204 tuner_info( "I am in mode %u and I should switch to mode %i\n", 388 tuner_info( "I am in mode %u and I should switch to mode %i\n",
205 priv->mode, new_mode); 389 priv->mode, new_mode);
206 390
@@ -213,23 +397,31 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
213 change_digital_bandwidth = (priv->mode == T_DIGITAL_TV 397 change_digital_bandwidth = (priv->mode == T_DIGITAL_TV
214 && bandwidth != priv->bandwidth) ? 1 : 0; 398 && bandwidth != priv->bandwidth) ? 1 : 0;
215 tuner_info("old bandwidth %u, new bandwidth %u\n", priv->bandwidth, 399 tuner_info("old bandwidth %u, new bandwidth %u\n", priv->bandwidth,
216 bandwidth); 400 bandwidth);
217 401
218 if (priv->need_load_generic) { 402 if (priv->need_load_generic) {
219 if (priv->bandwidth==8)
220 name = firmware_8MHZ_INIT0;
221 else
222 name = firmware_INIT0;
223
224 /* Reset is needed before loading firmware */ 403 /* Reset is needed before loading firmware */
225 rc = priv->tuner_callback(priv->video_dev, 404 rc = priv->tuner_callback(priv->video_dev,
226 XC2028_TUNER_RESET, 0); 405 XC2028_TUNER_RESET, 0);
227 if (rc<0) 406 if (rc<0)
228 return rc; 407 return rc;
229 408
230 rc = load_firmware(fe,name); 409 type0=BASE;
231 if (rc<0) 410
411 if (priv->ctrl.type == XC2028_FIRM_MTS)
412 type0 |= MTS;
413
414 if (priv->bandwidth==8)
415 type0 |= F8MHZ;
416
417 /* FIXME: How to load FM and FM|INPUT1 firmwares? */
418
419 rc = load_firmware(fe, type0, &std0);
420 if (rc<0) {
421 tuner_info("Error %d while loading generic firmware\n",
422 rc);
232 return rc; 423 return rc;
424 }
233 425
234 priv->need_load_generic=0; 426 priv->need_load_generic=0;
235 priv->firm_type=0; 427 priv->firm_type=0;
@@ -241,49 +433,53 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
241 tuner_info("I should change bandwidth %u\n", 433 tuner_info("I should change bandwidth %u\n",
242 change_digital_bandwidth); 434 change_digital_bandwidth);
243 435
244 /* FIXME: t->std makes no sense here */
245 if (change_digital_bandwidth) { 436 if (change_digital_bandwidth) {
437
438 /*FIXME: Should allow selecting between D2620 and D2633 */
439 type |= D2620;
440
441 /* FIXME: When should select a DTV78 firmware?
442 */
246 switch(bandwidth) { 443 switch(bandwidth) {
247 case BANDWIDTH_8_MHZ: 444 case BANDWIDTH_8_MHZ:
248 std = V4L2_STD_DTV_8MHZ; 445 type |= DTV8;
249 break; 446 break;
250 447 case BANDWIDTH_7_MHZ:
251 case BANDWIDTH_7_MHZ: 448 type |= DTV7;
252 std = V4L2_STD_DTV_7MHZ;
253 break; 449 break;
254 450 case BANDWIDTH_6_MHZ:
255 case BANDWIDTH_6_MHZ: 451 /* FIXME: Should allow select also ATSC */
256 std = V4L2_STD_DTV_6MHZ; 452 type |= DTV6_QAM;
257 break; 453 break;
258 454
259 default: 455 default:
260 tuner_info("error: bandwidth not supported.\n"); 456 tuner_info("error: bandwidth not supported.\n");
261 }; 457 };
262 priv->bandwidth = bandwidth; 458 priv->bandwidth = bandwidth;
263 } 459 }
264 460
461 /* Load INIT1, if needed */
462 tuner_info("Trying to load init1 firmware\n");
463 type0 = BASE | INIT1 | priv->ctrl.type;
464 if (priv->ctrl.type == XC2028_FIRM_MTS)
465 type0 |= MTS;
466
467 /* FIXME: Should handle errors - if INIT1 found */
468 rc = load_firmware(fe, type0, &std0);
469
470 /* FIXME: Should add support for FM radio
471 */
472
473 if (priv->ctrl.type == XC2028_FIRM_MTS)
474 type |= MTS;
475
476 tuner_info("firmware standard to load: %08lx\n",(unsigned long) std);
265 if (priv->firm_type & std) { 477 if (priv->firm_type & std) {
266 tuner_info("xc3028: no need to load a std-specific firmware.\n"); 478 tuner_info("no need to load a std-specific firmware.\n");
267 return 0; 479 return 0;
268 } 480 }
269 481
270 rc = load_firmware(fe,firmware_INIT1); 482 rc = load_firmware(fe, type, &std);
271
272 if (std & V4L2_STD_MN)
273 name=firmware_MN;
274 else if (std & V4L2_STD_DTV_6MHZ)
275 name=firmware_6M;
276 else if (std & V4L2_STD_DTV_7MHZ)
277 name=firmware_7M;
278 else if (std & V4L2_STD_DTV_8MHZ)
279 name=firmware_8M;
280 else if (std & V4L2_STD_PAL_B)
281 name=firmware_B;
282 else
283 name=firmware_DK;
284
285 tuner_info("loading firmware named %s.\n", name);
286 rc = load_firmware(fe, name);
287 if (rc<0) 483 if (rc<0)
288 return rc; 484 return rc;
289 485
@@ -341,11 +537,11 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */,
341 537
342 tuner_info("%s called\n", __FUNCTION__); 538 tuner_info("%s called\n", __FUNCTION__);
343 539
540 mutex_lock(&priv->lock);
541
344 /* HACK: It seems that specific firmware need to be reloaded 542 /* HACK: It seems that specific firmware need to be reloaded
345 when freq is changed */ 543 when freq is changed */
346 544
347 mutex_lock(&priv->lock);
348
349 priv->firm_type=0; 545 priv->firm_type=0;
350 546
351 /* Reset GPIO 1 */ 547 /* Reset GPIO 1 */
@@ -365,7 +561,13 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */,
365 div = (freq - offset + DIV/2)/DIV; 561 div = (freq - offset + DIV/2)/DIV;
366 562
367 /* CMD= Set frequency */ 563 /* CMD= Set frequency */
368 send_seq(priv, {0x00, 0x02, 0x00, 0x00}); 564
565 if (priv->version<0x0202) {
566 send_seq(priv, {0x00, 0x02, 0x00, 0x00});
567 } else {
568 send_seq(priv, {0x80, 0x02, 0x00, 0x00});
569 }
570
369 rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); 571 rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
370 if (rc<0) 572 if (rc<0)
371 goto ret; 573 goto ret;
@@ -436,8 +638,13 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
436 638
437 priv->count--; 639 priv->count--;
438 640
439 if (!priv->count) 641 if (!priv->count) {
642 if (priv->ctrl.fname)
643 kfree(priv->ctrl.fname);
644
645 free_firmware(priv);
440 kfree (priv); 646 kfree (priv);
647 }
441 648
442 return 0; 649 return 0;
443} 650}
@@ -453,6 +660,32 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
453 return 0; 660 return 0;
454} 661}
455 662
663static int xc2028_set_config (struct dvb_frontend *fe, void *priv_cfg)
664{
665 struct xc2028_data *priv = fe->tuner_priv;
666 struct xc2028_ctrl *p = priv_cfg;
667
668 tuner_info("%s called\n", __FUNCTION__);
669
670 priv->ctrl.type = p->type;
671
672 if (p->fname) {
673 if (priv->ctrl.fname)
674 kfree(priv->ctrl.fname);
675
676 priv->ctrl.fname = kmalloc(strlen(p->fname)+1, GFP_KERNEL);
677 if (!priv->ctrl.fname)
678 return -ENOMEM;
679
680 free_firmware(priv);
681 strcpy(priv->ctrl.fname, p->fname);
682 }
683
684 tuner_info("%s OK\n", __FUNCTION__);
685
686 return 0;
687}
688
456static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = { 689static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
457 .info = { 690 .info = {
458 .name = "Xceive XC3028", 691 .name = "Xceive XC3028",
@@ -461,6 +694,7 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
461 .frequency_step = 50000, 694 .frequency_step = 50000,
462 }, 695 },
463 696
697 .set_config = xc2028_set_config,
464 .set_analog_params = xc2028_set_tv_freq, 698 .set_analog_params = xc2028_set_tv_freq,
465 .release = xc2028_dvb_release, 699 .release = xc2028_dvb_release,
466 .get_frequency = xc2028_get_frequency, 700 .get_frequency = xc2028_get_frequency,
@@ -513,6 +747,8 @@ int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap,
513 priv->dev = dev; 747 priv->dev = dev;
514 priv->video_dev = video_dev; 748 priv->video_dev = video_dev;
515 priv->tuner_callback = tuner_callback; 749 priv->tuner_callback = tuner_callback;
750 priv->max_len = 13;
751
516 752
517 mutex_init(&priv->lock); 753 mutex_init(&priv->lock);
518 754
diff --git a/drivers/media/video/tuner-xc2028.h b/drivers/media/video/tuner-xc2028.h
index d5a18a37d1c5..f4856f07bd08 100644
--- a/drivers/media/video/tuner-xc2028.h
+++ b/drivers/media/video/tuner-xc2028.h
@@ -9,13 +9,22 @@
9 9
10#include "dvb_frontend.h" 10#include "dvb_frontend.h"
11 11
12#define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
13
14enum xc2028_firm_type {
15 XC2028_FIRM_NORMAL,
16 XC2028_FIRM_MTS,
17};
18
19struct xc2028_ctrl {
20 enum xc2028_firm_type type;
21 char *fname;
22};
23
12/* xc2028 commands for callback */ 24/* xc2028 commands for callback */
13#define XC2028_TUNER_RESET 0 25#define XC2028_TUNER_RESET 0
14#define XC2028_RESET_CLK 1 26#define XC2028_RESET_CLK 1
15 27
16struct dvb_frontend;
17struct i2c_client;
18
19#if defined(CONFIG_TUNER_XC2028) || (defined(CONFIG_TUNER_XC2028_MODULE) && defined(MODULE)) 28#if defined(CONFIG_TUNER_XC2028) || (defined(CONFIG_TUNER_XC2028_MODULE) && defined(MODULE))
20int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap, 29int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap,
21 u8 i2c_addr, struct device *dev, void *video_dev, 30 u8 i2c_addr, struct device *dev, void *video_dev,