wis-sony-tuner.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. /*
  2. * Copyright (C) 2005-2006 Micronas USA Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License (Version 2) as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program; if not, write to the Free Software Foundation,
  15. * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/init.h>
  19. #include <linux/i2c.h>
  20. #include <linux/videodev2.h>
  21. #include <linux/slab.h>
  22. #include <media/tuner.h>
  23. #include <media/v4l2-common.h>
  24. #include <media/v4l2-ioctl.h>
  25. #include "wis-i2c.h"
  26. /* #define MPX_DEBUG */
  27. /* AS(IF/MPX) pin: LOW HIGH/OPEN
  28. * IF/MPX address: 0x42/0x40 0x43/0x44
  29. */
  30. #define IF_I2C_ADDR 0x43
  31. #define MPX_I2C_ADDR 0x44
  32. static v4l2_std_id force_band;
  33. static char force_band_str[] = "-";
  34. module_param_string(force_band, force_band_str, sizeof(force_band_str), 0644);
  35. static int force_mpx_mode = -1;
  36. module_param(force_mpx_mode, int, 0644);
  37. /* Store tuner info in the same format as tuner.c, so maybe we can put the
  38. * Sony tuner support in there. */
  39. struct sony_tunertype {
  40. char *name;
  41. unsigned char Vendor; /* unused here */
  42. unsigned char Type; /* unused here */
  43. unsigned short thresh1; /* band switch VHF_LO <=> VHF_HI */
  44. unsigned short thresh2; /* band switch VHF_HI <=> UHF */
  45. unsigned char VHF_L;
  46. unsigned char VHF_H;
  47. unsigned char UHF;
  48. unsigned char config;
  49. unsigned short IFPCoff;
  50. };
  51. /* This array is indexed by (tuner_type - 200) */
  52. static struct sony_tunertype sony_tuners[] = {
  53. { "Sony PAL+SECAM (BTF-PG472Z)", 0, 0,
  54. 16*144.25, 16*427.25, 0x01, 0x02, 0x04, 0xc6, 623},
  55. { "Sony NTSC_JP (BTF-PK467Z)", 0, 0,
  56. 16*220.25, 16*467.25, 0x01, 0x02, 0x04, 0xc6, 940},
  57. { "Sony NTSC (BTF-PB463Z)", 0, 0,
  58. 16*130.25, 16*364.25, 0x01, 0x02, 0x04, 0xc6, 732},
  59. };
  60. struct wis_sony_tuner {
  61. int type;
  62. v4l2_std_id std;
  63. unsigned int freq;
  64. int mpxmode;
  65. u32 audmode;
  66. };
  67. /* Basically the same as default_set_tv_freq() in tuner.c */
  68. static int set_freq(struct i2c_client *client, int freq)
  69. {
  70. struct wis_sony_tuner *t = i2c_get_clientdata(client);
  71. char *band_name;
  72. int n;
  73. int band_select;
  74. struct sony_tunertype *tun;
  75. u8 buffer[4];
  76. tun = &sony_tuners[t->type - 200];
  77. if (freq < tun->thresh1) {
  78. band_name = "VHF_L";
  79. band_select = tun->VHF_L;
  80. } else if (freq < tun->thresh2) {
  81. band_name = "VHF_H";
  82. band_select = tun->VHF_H;
  83. } else {
  84. band_name = "UHF";
  85. band_select = tun->UHF;
  86. }
  87. printk(KERN_DEBUG "wis-sony-tuner: tuning to frequency %d.%04d (%s)\n",
  88. freq / 16, (freq % 16) * 625, band_name);
  89. n = freq + tun->IFPCoff;
  90. buffer[0] = n >> 8;
  91. buffer[1] = n & 0xff;
  92. buffer[2] = tun->config;
  93. buffer[3] = band_select;
  94. i2c_master_send(client, buffer, 4);
  95. return 0;
  96. }
  97. static int mpx_write(struct i2c_client *client, int dev, int addr, int val)
  98. {
  99. u8 buffer[5];
  100. struct i2c_msg msg;
  101. buffer[0] = dev;
  102. buffer[1] = addr >> 8;
  103. buffer[2] = addr & 0xff;
  104. buffer[3] = val >> 8;
  105. buffer[4] = val & 0xff;
  106. msg.addr = MPX_I2C_ADDR;
  107. msg.flags = 0;
  108. msg.len = 5;
  109. msg.buf = buffer;
  110. i2c_transfer(client->adapter, &msg, 1);
  111. return 0;
  112. }
  113. /*
  114. * MPX register values for the BTF-PG472Z:
  115. *
  116. * FM_ NICAM_ SCART_
  117. * MODUS SOURCE ACB PRESCAL PRESCAL PRESCAL SYSTEM VOLUME
  118. * 10/0030 12/0008 12/0013 12/000E 12/0010 12/0000 10/0020 12/0000
  119. * ---------------------------------------------------------------
  120. * Auto 1003 0020 0100 2603 5000 XXXX 0001 7500
  121. *
  122. * B/G
  123. * Mono 1003 0020 0100 2603 5000 XXXX 0003 7500
  124. * A2 1003 0020 0100 2601 5000 XXXX 0003 7500
  125. * NICAM 1003 0120 0100 2603 5000 XXXX 0008 7500
  126. *
  127. * I
  128. * Mono 1003 0020 0100 2603 7900 XXXX 000A 7500
  129. * NICAM 1003 0120 0100 2603 7900 XXXX 000A 7500
  130. *
  131. * D/K
  132. * Mono 1003 0020 0100 2603 5000 XXXX 0004 7500
  133. * A2-1 1003 0020 0100 2601 5000 XXXX 0004 7500
  134. * A2-2 1003 0020 0100 2601 5000 XXXX 0005 7500
  135. * A2-3 1003 0020 0100 2601 5000 XXXX 0007 7500
  136. * NICAM 1003 0120 0100 2603 5000 XXXX 000B 7500
  137. *
  138. * L/L'
  139. * Mono 0003 0200 0100 7C03 5000 2200 0009 7500
  140. * NICAM 0003 0120 0100 7C03 5000 XXXX 0009 7500
  141. *
  142. * M
  143. * Mono 1003 0200 0100 2B03 5000 2B00 0002 7500
  144. *
  145. * For Asia, replace the 0x26XX in FM_PRESCALE with 0x14XX.
  146. *
  147. * Bilingual selection in A2/NICAM:
  148. *
  149. * High byte of SOURCE Left chan Right chan
  150. * 0x01 MAIN SUB
  151. * 0x03 MAIN MAIN
  152. * 0x04 SUB SUB
  153. *
  154. * Force mono in NICAM by setting the high byte of SOURCE to 0x02 (L/L') or
  155. * 0x00 (all other bands). Force mono in A2 with FMONO_A2:
  156. *
  157. * FMONO_A2
  158. * 10/0022
  159. * --------
  160. * Forced mono ON 07F0
  161. * Forced mono OFF 0190
  162. */
  163. static struct {
  164. enum { AUD_MONO, AUD_A2, AUD_NICAM, AUD_NICAM_L } audio_mode;
  165. u16 modus;
  166. u16 source;
  167. u16 acb;
  168. u16 fm_prescale;
  169. u16 nicam_prescale;
  170. u16 scart_prescale;
  171. u16 system;
  172. u16 volume;
  173. } mpx_audio_modes[] = {
  174. /* Auto */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
  175. 0x5000, 0x0000, 0x0001, 0x7500 },
  176. /* B/G Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
  177. 0x5000, 0x0000, 0x0003, 0x7500 },
  178. /* B/G A2 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
  179. 0x5000, 0x0000, 0x0003, 0x7500 },
  180. /* B/G NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603,
  181. 0x5000, 0x0000, 0x0008, 0x7500 },
  182. /* I Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
  183. 0x7900, 0x0000, 0x000A, 0x7500 },
  184. /* I NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603,
  185. 0x7900, 0x0000, 0x000A, 0x7500 },
  186. /* D/K Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
  187. 0x5000, 0x0000, 0x0004, 0x7500 },
  188. /* D/K A2-1 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
  189. 0x5000, 0x0000, 0x0004, 0x7500 },
  190. /* D/K A2-2 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
  191. 0x5000, 0x0000, 0x0005, 0x7500 },
  192. /* D/K A2-3 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
  193. 0x5000, 0x0000, 0x0007, 0x7500 },
  194. /* D/K NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603,
  195. 0x5000, 0x0000, 0x000B, 0x7500 },
  196. /* L/L' Mono */ { AUD_MONO, 0x0003, 0x0200, 0x0100, 0x7C03,
  197. 0x5000, 0x2200, 0x0009, 0x7500 },
  198. /* L/L' NICAM */{ AUD_NICAM_L, 0x0003, 0x0120, 0x0100, 0x7C03,
  199. 0x5000, 0x0000, 0x0009, 0x7500 },
  200. };
  201. #define MPX_NUM_MODES ARRAY_SIZE(mpx_audio_modes)
  202. static int mpx_setup(struct i2c_client *client)
  203. {
  204. struct wis_sony_tuner *t = i2c_get_clientdata(client);
  205. u16 source = 0;
  206. u8 buffer[3];
  207. struct i2c_msg msg;
  208. /* reset MPX */
  209. buffer[0] = 0x00;
  210. buffer[1] = 0x80;
  211. buffer[2] = 0x00;
  212. msg.addr = MPX_I2C_ADDR;
  213. msg.flags = 0;
  214. msg.len = 3;
  215. msg.buf = buffer;
  216. i2c_transfer(client->adapter, &msg, 1);
  217. buffer[1] = 0x00;
  218. i2c_transfer(client->adapter, &msg, 1);
  219. if (mpx_audio_modes[t->mpxmode].audio_mode != AUD_MONO) {
  220. switch (t->audmode) {
  221. case V4L2_TUNER_MODE_MONO:
  222. switch (mpx_audio_modes[t->mpxmode].audio_mode) {
  223. case AUD_A2:
  224. source = mpx_audio_modes[t->mpxmode].source;
  225. break;
  226. case AUD_NICAM:
  227. source = 0x0000;
  228. break;
  229. case AUD_NICAM_L:
  230. source = 0x0200;
  231. break;
  232. default:
  233. break;
  234. }
  235. break;
  236. case V4L2_TUNER_MODE_STEREO:
  237. source = mpx_audio_modes[t->mpxmode].source;
  238. break;
  239. case V4L2_TUNER_MODE_LANG1:
  240. source = 0x0300;
  241. break;
  242. case V4L2_TUNER_MODE_LANG2:
  243. source = 0x0400;
  244. break;
  245. }
  246. source |= mpx_audio_modes[t->mpxmode].source & 0x00ff;
  247. } else
  248. source = mpx_audio_modes[t->mpxmode].source;
  249. mpx_write(client, 0x10, 0x0030, mpx_audio_modes[t->mpxmode].modus);
  250. mpx_write(client, 0x12, 0x0008, source);
  251. mpx_write(client, 0x12, 0x0013, mpx_audio_modes[t->mpxmode].acb);
  252. mpx_write(client, 0x12, 0x000e,
  253. mpx_audio_modes[t->mpxmode].fm_prescale);
  254. mpx_write(client, 0x12, 0x0010,
  255. mpx_audio_modes[t->mpxmode].nicam_prescale);
  256. mpx_write(client, 0x12, 0x000d,
  257. mpx_audio_modes[t->mpxmode].scart_prescale);
  258. mpx_write(client, 0x10, 0x0020, mpx_audio_modes[t->mpxmode].system);
  259. mpx_write(client, 0x12, 0x0000, mpx_audio_modes[t->mpxmode].volume);
  260. if (mpx_audio_modes[t->mpxmode].audio_mode == AUD_A2)
  261. mpx_write(client, 0x10, 0x0022,
  262. t->audmode == V4L2_TUNER_MODE_MONO ? 0x07f0 : 0x0190);
  263. #ifdef MPX_DEBUG
  264. {
  265. u8 buf1[3], buf2[2];
  266. struct i2c_msg msgs[2];
  267. printk(KERN_DEBUG "wis-sony-tuner: MPX registers: %04x %04x "
  268. "%04x %04x %04x %04x %04x %04x\n",
  269. mpx_audio_modes[t->mpxmode].modus,
  270. source,
  271. mpx_audio_modes[t->mpxmode].acb,
  272. mpx_audio_modes[t->mpxmode].fm_prescale,
  273. mpx_audio_modes[t->mpxmode].nicam_prescale,
  274. mpx_audio_modes[t->mpxmode].scart_prescale,
  275. mpx_audio_modes[t->mpxmode].system,
  276. mpx_audio_modes[t->mpxmode].volume);
  277. buf1[0] = 0x11;
  278. buf1[1] = 0x00;
  279. buf1[2] = 0x7e;
  280. msgs[0].addr = MPX_I2C_ADDR;
  281. msgs[0].flags = 0;
  282. msgs[0].len = 3;
  283. msgs[0].buf = buf1;
  284. msgs[1].addr = MPX_I2C_ADDR;
  285. msgs[1].flags = I2C_M_RD;
  286. msgs[1].len = 2;
  287. msgs[1].buf = buf2;
  288. i2c_transfer(client->adapter, msgs, 2);
  289. printk(KERN_DEBUG "wis-sony-tuner: MPX system: %02x%02x\n",
  290. buf2[0], buf2[1]);
  291. buf1[0] = 0x11;
  292. buf1[1] = 0x02;
  293. buf1[2] = 0x00;
  294. i2c_transfer(client->adapter, msgs, 2);
  295. printk(KERN_DEBUG "wis-sony-tuner: MPX status: %02x%02x\n",
  296. buf2[0], buf2[1]);
  297. }
  298. #endif
  299. return 0;
  300. }
  301. /*
  302. * IF configuration values for the BTF-PG472Z:
  303. *
  304. * B/G: 0x94 0x70 0x49
  305. * I: 0x14 0x70 0x4a
  306. * D/K: 0x14 0x70 0x4b
  307. * L: 0x04 0x70 0x4b
  308. * L': 0x44 0x70 0x53
  309. * M: 0x50 0x30 0x4c
  310. */
  311. static int set_if(struct i2c_client *client)
  312. {
  313. struct wis_sony_tuner *t = i2c_get_clientdata(client);
  314. u8 buffer[4];
  315. struct i2c_msg msg;
  316. int default_mpx_mode = 0;
  317. /* configure IF */
  318. buffer[0] = 0;
  319. if (t->std & V4L2_STD_PAL_BG) {
  320. buffer[1] = 0x94;
  321. buffer[2] = 0x70;
  322. buffer[3] = 0x49;
  323. default_mpx_mode = 1;
  324. } else if (t->std & V4L2_STD_PAL_I) {
  325. buffer[1] = 0x14;
  326. buffer[2] = 0x70;
  327. buffer[3] = 0x4a;
  328. default_mpx_mode = 4;
  329. } else if (t->std & V4L2_STD_PAL_DK) {
  330. buffer[1] = 0x14;
  331. buffer[2] = 0x70;
  332. buffer[3] = 0x4b;
  333. default_mpx_mode = 6;
  334. } else if (t->std & V4L2_STD_SECAM_L) {
  335. buffer[1] = 0x04;
  336. buffer[2] = 0x70;
  337. buffer[3] = 0x4b;
  338. default_mpx_mode = 11;
  339. }
  340. msg.addr = IF_I2C_ADDR;
  341. msg.flags = 0;
  342. msg.len = 4;
  343. msg.buf = buffer;
  344. i2c_transfer(client->adapter, &msg, 1);
  345. /* Select MPX mode if not forced by the user */
  346. if (force_mpx_mode >= 0 && force_mpx_mode < MPX_NUM_MODES)
  347. t->mpxmode = force_mpx_mode;
  348. else
  349. t->mpxmode = default_mpx_mode;
  350. printk(KERN_DEBUG "wis-sony-tuner: setting MPX to mode %d\n",
  351. t->mpxmode);
  352. mpx_setup(client);
  353. return 0;
  354. }
  355. static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
  356. {
  357. struct wis_sony_tuner *t = i2c_get_clientdata(client);
  358. switch (cmd) {
  359. #if 0
  360. #ifdef TUNER_SET_TYPE_ADDR
  361. case TUNER_SET_TYPE_ADDR:
  362. {
  363. struct tuner_setup *tun_setup = arg;
  364. int *type = &tun_setup->type;
  365. #else
  366. case TUNER_SET_TYPE:
  367. {
  368. int *type = arg;
  369. #endif
  370. if (t->type >= 0) {
  371. if (t->type != *type)
  372. printk(KERN_ERR "wis-sony-tuner: type already "
  373. "set to %d, ignoring request for %d\n",
  374. t->type, *type);
  375. break;
  376. }
  377. t->type = *type;
  378. switch (t->type) {
  379. case TUNER_SONY_BTF_PG472Z:
  380. switch (force_band_str[0]) {
  381. case 'b':
  382. case 'B':
  383. case 'g':
  384. case 'G':
  385. printk(KERN_INFO "wis-sony-tuner: forcing "
  386. "tuner to PAL-B/G bands\n");
  387. force_band = V4L2_STD_PAL_BG;
  388. break;
  389. case 'i':
  390. case 'I':
  391. printk(KERN_INFO "wis-sony-tuner: forcing "
  392. "tuner to PAL-I band\n");
  393. force_band = V4L2_STD_PAL_I;
  394. break;
  395. case 'd':
  396. case 'D':
  397. case 'k':
  398. case 'K':
  399. printk(KERN_INFO "wis-sony-tuner: forcing "
  400. "tuner to PAL-D/K bands\n");
  401. force_band = V4L2_STD_PAL_I;
  402. break;
  403. case 'l':
  404. case 'L':
  405. printk(KERN_INFO "wis-sony-tuner: forcing "
  406. "tuner to SECAM-L band\n");
  407. force_band = V4L2_STD_SECAM_L;
  408. break;
  409. default:
  410. force_band = 0;
  411. break;
  412. }
  413. if (force_band)
  414. t->std = force_band;
  415. else
  416. t->std = V4L2_STD_PAL_BG;
  417. set_if(client);
  418. break;
  419. case TUNER_SONY_BTF_PK467Z:
  420. t->std = V4L2_STD_NTSC_M_JP;
  421. break;
  422. case TUNER_SONY_BTF_PB463Z:
  423. t->std = V4L2_STD_NTSC_M;
  424. break;
  425. default:
  426. printk(KERN_ERR "wis-sony-tuner: tuner type %d is not "
  427. "supported by this module\n", *type);
  428. break;
  429. }
  430. if (type >= 0)
  431. printk(KERN_INFO
  432. "wis-sony-tuner: type set to %d (%s)\n",
  433. t->type, sony_tuners[t->type - 200].name);
  434. break;
  435. }
  436. #endif
  437. case VIDIOC_G_FREQUENCY:
  438. {
  439. struct v4l2_frequency *f = arg;
  440. f->frequency = t->freq;
  441. break;
  442. }
  443. case VIDIOC_S_FREQUENCY:
  444. {
  445. struct v4l2_frequency *f = arg;
  446. t->freq = f->frequency;
  447. set_freq(client, t->freq);
  448. break;
  449. }
  450. case VIDIOC_ENUMSTD:
  451. {
  452. struct v4l2_standard *std = arg;
  453. switch (t->type) {
  454. case TUNER_SONY_BTF_PG472Z:
  455. switch (std->index) {
  456. case 0:
  457. v4l2_video_std_construct(std,
  458. V4L2_STD_PAL_BG, "PAL-B/G");
  459. break;
  460. case 1:
  461. v4l2_video_std_construct(std,
  462. V4L2_STD_PAL_I, "PAL-I");
  463. break;
  464. case 2:
  465. v4l2_video_std_construct(std,
  466. V4L2_STD_PAL_DK, "PAL-D/K");
  467. break;
  468. case 3:
  469. v4l2_video_std_construct(std,
  470. V4L2_STD_SECAM_L, "SECAM-L");
  471. break;
  472. default:
  473. std->id = 0; /* hack to indicate EINVAL */
  474. break;
  475. }
  476. break;
  477. case TUNER_SONY_BTF_PK467Z:
  478. if (std->index != 0) {
  479. std->id = 0; /* hack to indicate EINVAL */
  480. break;
  481. }
  482. v4l2_video_std_construct(std,
  483. V4L2_STD_NTSC_M_JP, "NTSC-J");
  484. break;
  485. case TUNER_SONY_BTF_PB463Z:
  486. if (std->index != 0) {
  487. std->id = 0; /* hack to indicate EINVAL */
  488. break;
  489. }
  490. v4l2_video_std_construct(std, V4L2_STD_NTSC_M, "NTSC");
  491. break;
  492. }
  493. break;
  494. }
  495. case VIDIOC_G_STD:
  496. {
  497. v4l2_std_id *std = arg;
  498. *std = t->std;
  499. break;
  500. }
  501. case VIDIOC_S_STD:
  502. {
  503. v4l2_std_id *std = arg;
  504. v4l2_std_id old = t->std;
  505. switch (t->type) {
  506. case TUNER_SONY_BTF_PG472Z:
  507. if (force_band && (*std & force_band) != *std &&
  508. *std != V4L2_STD_PAL &&
  509. *std != V4L2_STD_SECAM) {
  510. printk(KERN_DEBUG "wis-sony-tuner: ignoring "
  511. "requested TV standard in "
  512. "favor of force_band value\n");
  513. t->std = force_band;
  514. } else if (*std & V4L2_STD_PAL_BG) { /* default */
  515. t->std = V4L2_STD_PAL_BG;
  516. } else if (*std & V4L2_STD_PAL_I) {
  517. t->std = V4L2_STD_PAL_I;
  518. } else if (*std & V4L2_STD_PAL_DK) {
  519. t->std = V4L2_STD_PAL_DK;
  520. } else if (*std & V4L2_STD_SECAM_L) {
  521. t->std = V4L2_STD_SECAM_L;
  522. } else {
  523. printk(KERN_ERR "wis-sony-tuner: TV standard "
  524. "not supported\n");
  525. *std = 0; /* hack to indicate EINVAL */
  526. break;
  527. }
  528. if (old != t->std)
  529. set_if(client);
  530. break;
  531. case TUNER_SONY_BTF_PK467Z:
  532. if (!(*std & V4L2_STD_NTSC_M_JP)) {
  533. printk(KERN_ERR "wis-sony-tuner: TV standard "
  534. "not supported\n");
  535. *std = 0; /* hack to indicate EINVAL */
  536. }
  537. break;
  538. case TUNER_SONY_BTF_PB463Z:
  539. if (!(*std & V4L2_STD_NTSC_M)) {
  540. printk(KERN_ERR "wis-sony-tuner: TV standard "
  541. "not supported\n");
  542. *std = 0; /* hack to indicate EINVAL */
  543. }
  544. break;
  545. }
  546. break;
  547. }
  548. case VIDIOC_QUERYSTD:
  549. {
  550. v4l2_std_id *std = arg;
  551. switch (t->type) {
  552. case TUNER_SONY_BTF_PG472Z:
  553. if (force_band)
  554. *std = force_band;
  555. else
  556. *std = V4L2_STD_PAL_BG | V4L2_STD_PAL_I |
  557. V4L2_STD_PAL_DK | V4L2_STD_SECAM_L;
  558. break;
  559. case TUNER_SONY_BTF_PK467Z:
  560. *std = V4L2_STD_NTSC_M_JP;
  561. break;
  562. case TUNER_SONY_BTF_PB463Z:
  563. *std = V4L2_STD_NTSC_M;
  564. break;
  565. }
  566. break;
  567. }
  568. case VIDIOC_G_TUNER:
  569. {
  570. struct v4l2_tuner *tun = arg;
  571. memset(tun, 0, sizeof(*tun));
  572. strcpy(tun->name, "Television");
  573. tun->type = V4L2_TUNER_ANALOG_TV;
  574. tun->rangelow = 0UL; /* does anything use these? */
  575. tun->rangehigh = 0xffffffffUL;
  576. switch (t->type) {
  577. case TUNER_SONY_BTF_PG472Z:
  578. tun->capability = V4L2_TUNER_CAP_NORM |
  579. V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
  580. V4L2_TUNER_CAP_LANG2;
  581. tun->rxsubchans = V4L2_TUNER_SUB_MONO |
  582. V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_LANG1 |
  583. V4L2_TUNER_SUB_LANG2;
  584. break;
  585. case TUNER_SONY_BTF_PK467Z:
  586. case TUNER_SONY_BTF_PB463Z:
  587. tun->capability = V4L2_TUNER_CAP_STEREO;
  588. tun->rxsubchans = V4L2_TUNER_SUB_MONO |
  589. V4L2_TUNER_SUB_STEREO;
  590. break;
  591. }
  592. tun->audmode = t->audmode;
  593. return 0;
  594. }
  595. case VIDIOC_S_TUNER:
  596. {
  597. struct v4l2_tuner *tun = arg;
  598. switch (t->type) {
  599. case TUNER_SONY_BTF_PG472Z:
  600. if (tun->audmode != t->audmode) {
  601. t->audmode = tun->audmode;
  602. mpx_setup(client);
  603. }
  604. break;
  605. case TUNER_SONY_BTF_PK467Z:
  606. case TUNER_SONY_BTF_PB463Z:
  607. break;
  608. }
  609. return 0;
  610. }
  611. default:
  612. break;
  613. }
  614. return 0;
  615. }
  616. static int wis_sony_tuner_probe(struct i2c_client *client,
  617. const struct i2c_device_id *id)
  618. {
  619. struct i2c_adapter *adapter = client->adapter;
  620. struct wis_sony_tuner *t;
  621. if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
  622. return -ENODEV;
  623. t = kmalloc(sizeof(struct wis_sony_tuner), GFP_KERNEL);
  624. if (t == NULL)
  625. return -ENOMEM;
  626. t->type = -1;
  627. t->freq = 0;
  628. t->mpxmode = 0;
  629. t->audmode = V4L2_TUNER_MODE_STEREO;
  630. i2c_set_clientdata(client, t);
  631. printk(KERN_DEBUG
  632. "wis-sony-tuner: initializing tuner at address %d on %s\n",
  633. client->addr, adapter->name);
  634. return 0;
  635. }
  636. static int wis_sony_tuner_remove(struct i2c_client *client)
  637. {
  638. struct wis_sony_tuner *t = i2c_get_clientdata(client);
  639. kfree(t);
  640. return 0;
  641. }
  642. static const struct i2c_device_id wis_sony_tuner_id[] = {
  643. { "wis_sony_tuner", 0 },
  644. { }
  645. };
  646. MODULE_DEVICE_TABLE(i2c, wis_sony_tuner_id);
  647. static struct i2c_driver wis_sony_tuner_driver = {
  648. .driver = {
  649. .name = "WIS Sony TV Tuner I2C driver",
  650. },
  651. .probe = wis_sony_tuner_probe,
  652. .remove = wis_sony_tuner_remove,
  653. .command = tuner_command,
  654. .id_table = wis_sony_tuner_id,
  655. };
  656. static int __init wis_sony_tuner_init(void)
  657. {
  658. return i2c_add_driver(&wis_sony_tuner_driver);
  659. }
  660. static void __exit wis_sony_tuner_cleanup(void)
  661. {
  662. i2c_del_driver(&wis_sony_tuner_driver);
  663. }
  664. module_init(wis_sony_tuner_init);
  665. module_exit(wis_sony_tuner_cleanup);
  666. MODULE_LICENSE("GPL v2");