Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (6133): tuner-simple: convert from tuner sub-driver into dvb_frontend module

Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
Acked-by: Mike Isely <isely@pobox.com>
Acked-by: Steven Toth <stoth@hauppauge.com>
Acked-by: Patrick Boettcher <pb@linuxtv.org>
Acked-by: Jarod Wilson <jwilson@redhat.com>
Acked-by: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>

authored by

Michael Krufky and committed by
Mauro Carvalho Chehab
4adad287 8d0936ed

+236 -112
+14 -3
drivers/media/video/tuner-core.c
··· 17 17 #include <linux/init.h> 18 18 #include <linux/videodev.h> 19 19 #include <media/tuner.h> 20 + #include <media/tuner-types.h> 20 21 #include <media/v4l2-common.h> 21 22 #include "tuner-driver.h" 22 23 #include "mt20xx.h" 23 24 #include "tda8290.h" 24 25 #include "tea5761.h" 25 26 #include "tea5767.h" 27 + #include "tuner-simple.h" 26 28 27 29 #define UNSET (-1U) 28 30 ··· 215 213 tda8290_attach(&t->fe, t->i2c.adapter, t->i2c.addr, &cfg); 216 214 } 217 215 216 + static void attach_simple_tuner(struct tuner *t) 217 + { 218 + struct simple_tuner_config cfg = { 219 + .type = t->type, 220 + .tun = &tuners[t->type] 221 + }; 222 + simple_tuner_attach(&t->fe, t->i2c.adapter, t->i2c.addr, &cfg); 223 + } 224 + 218 225 static void set_type(struct i2c_client *c, unsigned int type, 219 226 unsigned int new_mode_mask, unsigned int new_config, 220 227 int (*tuner_callback) (void *dev, int command,int arg)) ··· 301 290 buffer[2] = 0x86; 302 291 buffer[3] = 0x54; 303 292 i2c_master_send(c, buffer, 4); 304 - default_tuner_init(t); 293 + attach_simple_tuner(t); 305 294 break; 306 295 case TUNER_PHILIPS_TD1316: 307 296 buffer[0] = 0x0b; ··· 309 298 buffer[2] = 0x86; 310 299 buffer[3] = 0xa4; 311 300 i2c_master_send(c,buffer,4); 312 - default_tuner_init(t); 301 + attach_simple_tuner(t); 313 302 break; 314 303 case TUNER_TDA9887: 315 304 tda9887_tuner_init(t); 316 305 break; 317 306 default: 318 - default_tuner_init(t); 307 + attach_simple_tuner(t); 319 308 break; 320 309 } 321 310
-2
drivers/media/video/tuner-driver.h
··· 72 72 73 73 /* ------------------------------------------------------------------------ */ 74 74 75 - extern int default_tuner_init(struct tuner *t); 76 - 77 75 extern int tda9887_tuner_init(struct tuner *t); 78 76 79 77 /* ------------------------------------------------------------------------ */
+187 -107
drivers/media/video/tuner-simple.c
··· 1 1 /* 2 - * 3 2 * i2c tv tuner chip device driver 4 3 * controls all those simple 4-control-bytes style tuners. 4 + * 5 + * This "tuner-simple" module was split apart from the original "tuner" module. 5 6 */ 6 7 #include <linux/delay.h> 7 8 #include <linux/i2c.h> ··· 10 9 #include <media/tuner.h> 11 10 #include <media/v4l2-common.h> 12 11 #include <media/tuner-types.h> 13 - #include "tuner-driver.h" 12 + #include "tuner-i2c.h" 13 + #include "tuner-simple.h" 14 + 15 + static int debug = 0; 16 + module_param(debug, int, 0644); 17 + MODULE_PARM_DESC(debug, "enable verbose debug messages"); 18 + 19 + #define PREFIX "tuner-simple " 14 20 15 21 static int offset = 0; 16 22 module_param(offset, int, 0664); ··· 93 85 struct tuner_simple_priv { 94 86 u16 last_div; 95 87 struct tuner_i2c_props i2c_props; 88 + 89 + unsigned int type; 90 + struct tunertype *tun; 91 + 92 + u32 frequency; 96 93 }; 97 94 98 95 /* ---------------------------------------------------------------------- */ 99 96 100 - static int tuner_getstatus(struct tuner *t) 97 + static int tuner_getstatus(struct dvb_frontend *fe) 101 98 { 102 - struct tuner_simple_priv *priv = t->priv; 99 + struct tuner_simple_priv *priv = fe->tuner_priv; 103 100 unsigned char byte; 104 101 105 102 if (1 != tuner_i2c_xfer_recv(&priv->i2c_props,&byte,1)) ··· 113 100 return byte; 114 101 } 115 102 116 - static int tuner_signal(struct tuner *t) 103 + static int tuner_signal(struct dvb_frontend *fe) 117 104 { 118 - return (tuner_getstatus(t) & TUNER_SIGNAL) << 13; 105 + return (tuner_getstatus(fe) & TUNER_SIGNAL) << 13; 119 106 } 120 107 121 - static int tuner_stereo(struct tuner *t) 108 + static int tuner_stereo(struct dvb_frontend *fe) 122 109 { 110 + struct tuner_simple_priv *priv = fe->tuner_priv; 111 + 123 112 int stereo, status; 124 113 125 - status = tuner_getstatus(t); 114 + status = tuner_getstatus(fe); 126 115 127 - switch (t->type) { 116 + switch (priv->type) { 128 117 case TUNER_PHILIPS_FM1216ME_MK3: 129 118 case TUNER_PHILIPS_FM1236_MK3: 130 119 case TUNER_PHILIPS_FM1256_IH3: ··· 141 126 } 142 127 143 128 129 + static int simple_get_status(struct dvb_frontend *fe, u32 *status) 130 + { 131 + struct tuner_simple_priv *priv = fe->tuner_priv; 132 + int signal = tuner_signal(fe); 133 + 134 + *status = 0; 135 + 136 + if (signal) 137 + *status = TUNER_STATUS_LOCKED; 138 + if (tuner_stereo(fe)) 139 + *status |= TUNER_STATUS_STEREO; 140 + 141 + tuner_dbg("tuner-simple: Signal strength: %d\n", signal); 142 + 143 + return 0; 144 + } 145 + 144 146 /* ---------------------------------------------------------------------- */ 145 147 146 - static void default_set_tv_freq(struct tuner *t, unsigned int freq) 148 + static int simple_set_tv_freq(struct dvb_frontend *fe, 149 + struct analog_parameters *params) 147 150 { 148 - struct tuner_simple_priv *priv = t->priv; 151 + struct tuner_simple_priv *priv = fe->tuner_priv; 149 152 u8 config, cb, tuneraddr; 150 153 u16 div; 151 154 struct tunertype *tun; 152 155 u8 buffer[4]; 153 156 int rc, IFPCoff, i, j; 154 157 enum param_type desired_type; 155 - struct tuner_params *params; 158 + struct tuner_params *t_params; 156 159 157 - tun = &tuners[t->type]; 160 + tun = priv->tun; 158 161 159 162 /* IFPCoff = Video Intermediate Frequency - Vif: 160 163 940 =16*58.75 NTSC/J (Japan) ··· 186 153 171.2=16*10.70 FM Radio (at set_radio_freq) 187 154 */ 188 155 189 - if (t->std == V4L2_STD_NTSC_M_JP) { 156 + if (params->std == V4L2_STD_NTSC_M_JP) { 190 157 IFPCoff = 940; 191 158 desired_type = TUNER_PARAM_TYPE_NTSC; 192 - } else if ((t->std & V4L2_STD_MN) && 193 - !(t->std & ~V4L2_STD_MN)) { 159 + } else if ((params->std & V4L2_STD_MN) && 160 + !(params->std & ~V4L2_STD_MN)) { 194 161 IFPCoff = 732; 195 162 desired_type = TUNER_PARAM_TYPE_NTSC; 196 - } else if (t->std == V4L2_STD_SECAM_LC) { 163 + } else if (params->std == V4L2_STD_SECAM_LC) { 197 164 IFPCoff = 543; 198 165 desired_type = TUNER_PARAM_TYPE_SECAM; 199 166 } else { ··· 206 173 continue; 207 174 break; 208 175 } 209 - /* use default tuner_params if desired_type not available */ 176 + /* use default tuner_t_params if desired_type not available */ 210 177 if (desired_type != tun->params[j].type) { 211 - tuner_dbg("IFPCoff = %d: tuner_params undefined for tuner %d\n", 212 - IFPCoff,t->type); 178 + tuner_dbg("IFPCoff = %d: tuner_t_params undefined for tuner %d\n", 179 + IFPCoff, priv->type); 213 180 j = 0; 214 181 } 215 - params = &tun->params[j]; 182 + t_params = &tun->params[j]; 216 183 217 - for (i = 0; i < params->count; i++) { 218 - if (freq > params->ranges[i].limit) 184 + for (i = 0; i < t_params->count; i++) { 185 + if (params->frequency > t_params->ranges[i].limit) 219 186 continue; 220 187 break; 221 188 } 222 - if (i == params->count) { 189 + if (i == t_params->count) { 223 190 tuner_dbg("TV frequency out of range (%d > %d)", 224 - freq, params->ranges[i - 1].limit); 225 - freq = params->ranges[--i].limit; 191 + params->frequency, t_params->ranges[i - 1].limit); 192 + params->frequency = t_params->ranges[--i].limit; 226 193 } 227 - config = params->ranges[i].config; 228 - cb = params->ranges[i].cb; 194 + config = t_params->ranges[i].config; 195 + cb = t_params->ranges[i].cb; 229 196 /* i == 0 -> VHF_LO 230 197 * i == 1 -> VHF_HI 231 198 * i == 2 -> UHF */ 232 199 tuner_dbg("tv: param %d, range %d\n",j,i); 233 200 234 - div=freq + IFPCoff + offset; 201 + div=params->frequency + IFPCoff + offset; 235 202 236 203 tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n", 237 - freq / 16, freq % 16 * 100 / 16, 204 + params->frequency / 16, params->frequency % 16 * 100 / 16, 238 205 IFPCoff / 16, IFPCoff % 16 * 100 / 16, 239 206 offset / 16, offset % 16 * 100 / 16, 240 207 div); 241 208 242 209 /* tv norm specific stuff for multi-norm tuners */ 243 - switch (t->type) { 210 + switch (priv->type) { 244 211 case TUNER_PHILIPS_SECAM: // FI1216MF 245 212 /* 0x01 -> ??? no change ??? */ 246 213 /* 0x02 -> PAL BDGHI / SECAM L */ 247 214 /* 0x04 -> ??? PAL others / SECAM others ??? */ 248 215 cb &= ~0x03; 249 - if (t->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM 216 + if (params->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM 250 217 cb |= PHILIPS_MF_SET_STD_L; 251 - else if (t->std & V4L2_STD_SECAM_LC) 218 + else if (params->std & V4L2_STD_SECAM_LC) 252 219 cb |= PHILIPS_MF_SET_STD_LC; 253 220 else /* V4L2_STD_B|V4L2_STD_GH */ 254 221 cb |= PHILIPS_MF_SET_STD_BG; ··· 257 224 case TUNER_TEMIC_4046FM5: 258 225 cb &= ~0x0f; 259 226 260 - if (t->std & V4L2_STD_PAL_BG) { 227 + if (params->std & V4L2_STD_PAL_BG) { 261 228 cb |= TEMIC_SET_PAL_BG; 262 229 263 - } else if (t->std & V4L2_STD_PAL_I) { 230 + } else if (params->std & V4L2_STD_PAL_I) { 264 231 cb |= TEMIC_SET_PAL_I; 265 232 266 - } else if (t->std & V4L2_STD_PAL_DK) { 233 + } else if (params->std & V4L2_STD_PAL_DK) { 267 234 cb |= TEMIC_SET_PAL_DK; 268 235 269 - } else if (t->std & V4L2_STD_SECAM_L) { 236 + } else if (params->std & V4L2_STD_SECAM_L) { 270 237 cb |= TEMIC_SET_PAL_L; 271 238 272 239 } ··· 275 242 case TUNER_PHILIPS_FQ1216ME: 276 243 cb &= ~0x0f; 277 244 278 - if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { 245 + if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { 279 246 cb |= PHILIPS_SET_PAL_BGDK; 280 247 281 - } else if (t->std & V4L2_STD_PAL_I) { 248 + } else if (params->std & V4L2_STD_PAL_I) { 282 249 cb |= PHILIPS_SET_PAL_I; 283 250 284 - } else if (t->std & V4L2_STD_SECAM_L) { 251 + } else if (params->std & V4L2_STD_SECAM_L) { 285 252 cb |= PHILIPS_SET_PAL_L; 286 253 287 254 } ··· 293 260 /* 0x02 -> NTSC antenna input 1 */ 294 261 /* 0x03 -> NTSC antenna input 2 */ 295 262 cb &= ~0x03; 296 - if (!(t->std & V4L2_STD_ATSC)) 263 + if (!(params->std & V4L2_STD_ATSC)) 297 264 cb |= 2; 298 265 /* FIXME: input */ 299 266 break; ··· 313 280 buffer[2] = 0x17; 314 281 buffer[3] = 0x00; 315 282 cb &= ~0x40; 316 - if (t->std & V4L2_STD_ATSC) { 283 + if (params->std & V4L2_STD_ATSC) { 317 284 cb |= 0x40; 318 285 buffer[1] = 0x04; 319 286 } ··· 329 296 break; 330 297 } 331 298 332 - if (params->cb_first_if_lower_freq && div < priv->last_div) { 299 + if (t_params->cb_first_if_lower_freq && div < priv->last_div) { 333 300 buffer[0] = config; 334 301 buffer[1] = cb; 335 302 buffer[2] = (div>>8) & 0x7f; ··· 341 308 buffer[3] = cb; 342 309 } 343 310 priv->last_div = div; 344 - if (params->has_tda9887) { 311 + if (t_params->has_tda9887) { 345 312 int config = 0; 346 - int is_secam_l = (t->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) && 347 - !(t->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)); 313 + int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) && 314 + !(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)); 348 315 349 - if (t->std == V4L2_STD_SECAM_LC) { 350 - if (params->port1_active ^ params->port1_invert_for_secam_lc) 316 + if (params->std == V4L2_STD_SECAM_LC) { 317 + if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc) 351 318 config |= TDA9887_PORT1_ACTIVE; 352 - if (params->port2_active ^ params->port2_invert_for_secam_lc) 319 + if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc) 353 320 config |= TDA9887_PORT2_ACTIVE; 354 321 } 355 322 else { 356 - if (params->port1_active) 323 + if (t_params->port1_active) 357 324 config |= TDA9887_PORT1_ACTIVE; 358 - if (params->port2_active) 325 + if (t_params->port2_active) 359 326 config |= TDA9887_PORT2_ACTIVE; 360 327 } 361 - if (params->intercarrier_mode) 328 + if (t_params->intercarrier_mode) 362 329 config |= TDA9887_INTERCARRIER; 363 330 if (is_secam_l) { 364 - if (i == 0 && params->default_top_secam_low) 365 - config |= TDA9887_TOP(params->default_top_secam_low); 366 - else if (i == 1 && params->default_top_secam_mid) 367 - config |= TDA9887_TOP(params->default_top_secam_mid); 368 - else if (params->default_top_secam_high) 369 - config |= TDA9887_TOP(params->default_top_secam_high); 331 + if (i == 0 && t_params->default_top_secam_low) 332 + config |= TDA9887_TOP(t_params->default_top_secam_low); 333 + else if (i == 1 && t_params->default_top_secam_mid) 334 + config |= TDA9887_TOP(t_params->default_top_secam_mid); 335 + else if (t_params->default_top_secam_high) 336 + config |= TDA9887_TOP(t_params->default_top_secam_high); 370 337 } 371 338 else { 372 - if (i == 0 && params->default_top_low) 373 - config |= TDA9887_TOP(params->default_top_low); 374 - else if (i == 1 && params->default_top_mid) 375 - config |= TDA9887_TOP(params->default_top_mid); 376 - else if (params->default_top_high) 377 - config |= TDA9887_TOP(params->default_top_high); 339 + if (i == 0 && t_params->default_top_low) 340 + config |= TDA9887_TOP(t_params->default_top_low); 341 + else if (i == 1 && t_params->default_top_mid) 342 + config |= TDA9887_TOP(t_params->default_top_mid); 343 + else if (t_params->default_top_high) 344 + config |= TDA9887_TOP(t_params->default_top_high); 378 345 } 379 - if (params->default_pll_gating_18) 346 + if (t_params->default_pll_gating_18) 380 347 config |= TDA9887_GATING_18; 381 348 i2c_clients_command(priv->i2c_props.adap, TDA9887_SET_CONFIG, &config); 382 349 } ··· 386 353 if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) 387 354 tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); 388 355 389 - switch (t->type) { 356 + switch (priv->type) { 390 357 case TUNER_LG_TDVS_H06XF: 391 358 /* Set the Auxiliary Byte. */ 392 359 buffer[0] = buffer[2]; ··· 407 374 /* Wait until the PLL locks */ 408 375 for (;;) { 409 376 if (time_after(jiffies,timeout)) 410 - return; 377 + return 0; 411 378 if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) { 412 379 tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc); 413 380 break; ··· 431 398 break; 432 399 } 433 400 } 401 + return 0; 434 402 } 435 403 436 - static void default_set_radio_freq(struct tuner *t, unsigned int freq) 404 + static int simple_set_radio_freq(struct dvb_frontend *fe, 405 + struct analog_parameters *params) 437 406 { 438 407 struct tunertype *tun; 439 - struct tuner_simple_priv *priv = t->priv; 408 + struct tuner_simple_priv *priv = fe->tuner_priv; 440 409 u8 buffer[4]; 441 410 u16 div; 442 411 int rc, j; 443 - struct tuner_params *params; 412 + struct tuner_params *t_params; 413 + unsigned int freq = params->frequency; 444 414 445 - tun = &tuners[t->type]; 415 + tun = priv->tun; 446 416 447 417 for (j = tun->count-1; j > 0; j--) 448 418 if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO) 449 419 break; 450 - /* default params (j=0) will be used if desired type wasn't found */ 451 - params = &tun->params[j]; 420 + /* default t_params (j=0) will be used if desired type wasn't found */ 421 + t_params = &tun->params[j]; 452 422 453 423 /* Select Radio 1st IF used */ 454 - switch (params->radio_if) { 424 + switch (t_params->radio_if) { 455 425 case 0: /* 10.7 MHz */ 456 426 freq += (unsigned int)(10.7*16000); 457 427 break; ··· 465 429 freq += (unsigned int)(41.3*16000); 466 430 break; 467 431 default: 468 - tuner_warn("Unsupported radio_if value %d\n", params->radio_if); 469 - return; 432 + tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if); 433 + return 0; 470 434 } 471 435 472 436 /* Bandswitch byte */ 473 - switch (t->type) { 437 + switch (priv->type) { 474 438 case TUNER_TENA_9533_DI: 475 439 case TUNER_YMEC_TVF_5533MF: 476 - tuner_dbg ("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n"); 477 - return; 440 + tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n"); 441 + return 0; 478 442 case TUNER_PHILIPS_FM1216ME_MK3: 479 443 case TUNER_PHILIPS_FM1236_MK3: 480 444 case TUNER_PHILIPS_FMD1216ME_MK3: ··· 497 461 break; 498 462 } 499 463 500 - buffer[2] = (params->ranges[0].config & ~TUNER_RATIO_MASK) | 464 + buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) | 501 465 TUNER_RATIO_SELECT_50; /* 50 kHz step */ 502 466 503 467 /* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps ··· 505 469 freq * (1/800) */ 506 470 div = (freq + 400) / 800; 507 471 508 - if (params->cb_first_if_lower_freq && div < priv->last_div) { 472 + if (t_params->cb_first_if_lower_freq && div < priv->last_div) { 509 473 buffer[0] = buffer[2]; 510 474 buffer[1] = buffer[3]; 511 475 buffer[2] = (div>>8) & 0x7f; ··· 519 483 buffer[0],buffer[1],buffer[2],buffer[3]); 520 484 priv->last_div = div; 521 485 522 - if (params->has_tda9887) { 486 + if (t_params->has_tda9887) { 523 487 int config = 0; 524 - if (params->port1_active && !params->port1_fm_high_sensitivity) 488 + if (t_params->port1_active && !t_params->port1_fm_high_sensitivity) 525 489 config |= TDA9887_PORT1_ACTIVE; 526 - if (params->port2_active && !params->port2_fm_high_sensitivity) 490 + if (t_params->port2_active && !t_params->port2_fm_high_sensitivity) 527 491 config |= TDA9887_PORT2_ACTIVE; 528 - if (params->intercarrier_mode) 492 + if (t_params->intercarrier_mode) 529 493 config |= TDA9887_INTERCARRIER; 530 - /* if (params->port1_set_for_fm_mono) 494 + /* if (t_params->port1_set_for_fm_mono) 531 495 config &= ~TDA9887_PORT1_ACTIVE;*/ 532 - if (params->fm_gain_normal) 496 + if (t_params->fm_gain_normal) 533 497 config |= TDA9887_GAIN_NORMAL; 534 - if (params->radio_if == 2) 498 + if (t_params->radio_if == 2) 535 499 config |= TDA9887_RIF_41_3; 536 500 i2c_clients_command(priv->i2c_props.adap, TDA9887_SET_CONFIG, &config); 537 501 } 538 502 if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) 539 503 tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); 504 + 505 + return 0; 540 506 } 541 507 542 - static void tuner_release(struct tuner *t) 508 + static int simple_set_params(struct dvb_frontend *fe, 509 + struct analog_parameters *params) 543 510 { 544 - kfree(t->priv); 545 - t->priv = NULL; 511 + struct tuner_simple_priv *priv = fe->tuner_priv; 512 + int ret = -EINVAL; 513 + 514 + switch (params->mode) { 515 + case V4L2_TUNER_RADIO: 516 + ret = simple_set_radio_freq(fe, params); 517 + priv->frequency = params->frequency * 125 / 2; 518 + break; 519 + case V4L2_TUNER_ANALOG_TV: 520 + case V4L2_TUNER_DIGITAL_TV: 521 + ret = simple_set_tv_freq(fe, params); 522 + priv->frequency = params->frequency * 62500; 523 + break; 524 + } 525 + 526 + return ret; 546 527 } 547 528 548 - static struct tuner_operations simple_tuner_ops = { 549 - .set_tv_freq = default_set_tv_freq, 550 - .set_radio_freq = default_set_radio_freq, 551 - .has_signal = tuner_signal, 552 - .is_stereo = tuner_stereo, 553 - .release = tuner_release, 529 + 530 + static int simple_release(struct dvb_frontend *fe) 531 + { 532 + kfree(fe->tuner_priv); 533 + fe->tuner_priv = NULL; 534 + 535 + return 0; 536 + } 537 + 538 + static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency) 539 + { 540 + struct tuner_simple_priv *priv = fe->tuner_priv; 541 + *frequency = priv->frequency; 542 + return 0; 543 + } 544 + 545 + static struct dvb_tuner_ops simple_tuner_ops = { 546 + .set_analog_params = simple_set_params, 547 + .release = simple_release, 548 + .get_frequency = simple_get_frequency, 549 + .get_status = simple_get_status, 554 550 }; 555 551 556 - int default_tuner_init(struct tuner *t) 552 + struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, 553 + struct i2c_adapter *i2c_adap, 554 + u8 i2c_addr, 555 + struct simple_tuner_config *cfg) 557 556 { 558 557 struct tuner_simple_priv *priv = NULL; 559 558 560 559 priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL); 561 560 if (priv == NULL) 562 - return -ENOMEM; 563 - t->priv = priv; 561 + return NULL; 562 + fe->tuner_priv = priv; 564 563 565 - priv->i2c_props.addr = t->i2c.addr; 566 - priv->i2c_props.adap = t->i2c.adapter; 564 + priv->i2c_props.addr = i2c_addr; 565 + priv->i2c_props.adap = i2c_adap; 566 + priv->type = cfg->type; 567 + priv->tun = cfg->tun; 567 568 568 - tuner_info("type set to %d (%s)\n", 569 - t->type, tuners[t->type].name); 570 - strlcpy(t->i2c.name, tuners[t->type].name, sizeof(t->i2c.name)); 569 + memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops)); 571 570 572 - memcpy(&t->ops, &simple_tuner_ops, sizeof(struct tuner_operations)); 571 + tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name); 573 572 574 - return 0; 573 + strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name)); 574 + 575 + return fe; 575 576 } 577 + 578 + 579 + EXPORT_SYMBOL_GPL(simple_tuner_attach); 580 + 581 + MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver"); 582 + MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); 583 + MODULE_LICENSE("GPL"); 576 584 577 585 /* 578 586 * Overrides for Emacs so that we follow Linus's tabbing style.
+35
drivers/media/video/tuner-simple.h
··· 1 + /* 2 + This program is free software; you can redistribute it and/or modify 3 + it under the terms of the GNU General Public License as published by 4 + the Free Software Foundation; either version 2 of the License, or 5 + (at your option) any later version. 6 + 7 + This program is distributed in the hope that it will be useful, 8 + but WITHOUT ANY WARRANTY; without even the implied warranty of 9 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 + GNU General Public License for more details. 11 + 12 + You should have received a copy of the GNU General Public License 13 + along with this program; if not, write to the Free Software 14 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 15 + */ 16 + 17 + #ifndef __TUNER_SIMPLE_H__ 18 + #define __TUNER_SIMPLE_H__ 19 + 20 + #include <linux/i2c.h> 21 + #include "dvb_frontend.h" 22 + 23 + struct simple_tuner_config 24 + { 25 + /* chip type */ 26 + unsigned int type; 27 + struct tunertype *tun; 28 + }; 29 + 30 + extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, 31 + struct i2c_adapter *i2c_adap, 32 + u8 i2c_addr, 33 + struct simple_tuner_config *cfg); 34 + 35 + #endif /* __TUNER_SIMPLE_H__ */