matroxfb_maven.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299
  1. /*
  2. *
  3. * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
  4. *
  5. * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
  6. *
  7. * Portions Copyright (c) 2001 Matrox Graphics Inc.
  8. *
  9. * Version: 1.65 2002/08/14
  10. *
  11. * See matroxfb_base.c for contributors.
  12. *
  13. */
  14. #include "matroxfb_maven.h"
  15. #include "matroxfb_misc.h"
  16. #include "matroxfb_DAC1064.h"
  17. #include <linux/i2c.h>
  18. #include <linux/matroxfb.h>
  19. #include <asm/div64.h>
  20. #define MGATVO_B 1
  21. #define MGATVO_C 2
  22. static const struct maven_gamma {
  23. unsigned char reg83;
  24. unsigned char reg84;
  25. unsigned char reg85;
  26. unsigned char reg86;
  27. unsigned char reg87;
  28. unsigned char reg88;
  29. unsigned char reg89;
  30. unsigned char reg8a;
  31. unsigned char reg8b;
  32. } maven_gamma[] = {
  33. { 131, 57, 223, 15, 117, 212, 251, 91, 156},
  34. { 133, 61, 128, 63, 180, 147, 195, 100, 180},
  35. { 131, 19, 63, 31, 50, 66, 171, 64, 176},
  36. { 0, 0, 0, 31, 16, 16, 16, 100, 200},
  37. { 8, 23, 47, 73, 147, 244, 220, 80, 195},
  38. { 22, 43, 64, 80, 147, 115, 58, 85, 168},
  39. { 34, 60, 80, 214, 147, 212, 188, 85, 167},
  40. { 45, 77, 96, 216, 147, 99, 91, 85, 159},
  41. { 56, 76, 112, 107, 147, 212, 148, 64, 144},
  42. { 65, 91, 128, 137, 147, 196, 17, 69, 148},
  43. { 72, 104, 136, 138, 147, 180, 245, 73, 147},
  44. { 87, 116, 143, 126, 16, 83, 229, 77, 144},
  45. { 95, 119, 152, 254, 244, 83, 221, 77, 151},
  46. { 100, 129, 159, 156, 244, 148, 197, 77, 160},
  47. { 105, 141, 167, 247, 244, 132, 181, 84, 166},
  48. { 105, 147, 168, 247, 244, 245, 181, 90, 170},
  49. { 120, 153, 175, 248, 212, 229, 165, 90, 180},
  50. { 119, 156, 176, 248, 244, 229, 84, 74, 160},
  51. { 119, 158, 183, 248, 244, 229, 149, 78, 165}
  52. };
  53. /* Definition of the various controls */
  54. struct mctl {
  55. struct v4l2_queryctrl desc;
  56. size_t control;
  57. };
  58. #define BLMIN 0x0FF
  59. #define WLMAX 0x3FF
  60. static const struct mctl maven_controls[] =
  61. { { { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER,
  62. "brightness",
  63. 0, WLMAX - BLMIN, 1, 379 - BLMIN,
  64. 0,
  65. }, offsetof(struct matrox_fb_info, altout.tvo_params.brightness) },
  66. { { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
  67. "contrast",
  68. 0, 1023, 1, 127,
  69. 0,
  70. }, offsetof(struct matrox_fb_info, altout.tvo_params.contrast) },
  71. { { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
  72. "saturation",
  73. 0, 255, 1, 155,
  74. 0,
  75. }, offsetof(struct matrox_fb_info, altout.tvo_params.saturation) },
  76. { { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
  77. "hue",
  78. 0, 255, 1, 0,
  79. 0,
  80. }, offsetof(struct matrox_fb_info, altout.tvo_params.hue) },
  81. { { V4L2_CID_GAMMA, V4L2_CTRL_TYPE_INTEGER,
  82. "gamma",
  83. 0, ARRAY_SIZE(maven_gamma) - 1, 1, 3,
  84. 0,
  85. }, offsetof(struct matrox_fb_info, altout.tvo_params.gamma) },
  86. { { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN,
  87. "test output",
  88. 0, 1, 1, 0,
  89. 0,
  90. }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
  91. { { MATROXFB_CID_DEFLICKER, V4L2_CTRL_TYPE_INTEGER,
  92. "deflicker mode",
  93. 0, 2, 1, 0,
  94. 0,
  95. }, offsetof(struct matrox_fb_info, altout.tvo_params.deflicker) },
  96. };
  97. #define MAVCTRLS ARRAY_SIZE(maven_controls)
  98. /* Return: positive number: id found
  99. -EINVAL: id not found, return failure
  100. -ENOENT: id not found, create fake disabled control */
  101. static int get_ctrl_id(__u32 v4l2_id) {
  102. int i;
  103. for (i = 0; i < MAVCTRLS; i++) {
  104. if (v4l2_id < maven_controls[i].desc.id) {
  105. if (maven_controls[i].desc.id == 0x08000000) {
  106. return -EINVAL;
  107. }
  108. return -ENOENT;
  109. }
  110. if (v4l2_id == maven_controls[i].desc.id) {
  111. return i;
  112. }
  113. }
  114. return -EINVAL;
  115. }
  116. struct maven_data {
  117. struct matrox_fb_info* primary_head;
  118. struct i2c_client *client;
  119. int version;
  120. };
  121. static int* get_ctrl_ptr(struct maven_data* md, int idx) {
  122. return (int*)((char*)(md->primary_head) + maven_controls[idx].control);
  123. }
  124. static int maven_get_reg(struct i2c_client* c, char reg) {
  125. char dst;
  126. struct i2c_msg msgs[] = {{ c->addr, I2C_M_REV_DIR_ADDR, sizeof(reg), &reg },
  127. { c->addr, I2C_M_RD | I2C_M_NOSTART, sizeof(dst), &dst }};
  128. s32 err;
  129. err = i2c_transfer(c->adapter, msgs, 2);
  130. if (err < 0)
  131. printk(KERN_INFO "ReadReg(%d) failed\n", reg);
  132. return dst & 0xFF;
  133. }
  134. static int maven_set_reg(struct i2c_client* c, int reg, int val) {
  135. s32 err;
  136. err = i2c_smbus_write_byte_data(c, reg, val);
  137. if (err)
  138. printk(KERN_INFO "WriteReg(%d) failed\n", reg);
  139. return err;
  140. }
  141. static int maven_set_reg_pair(struct i2c_client* c, int reg, int val) {
  142. s32 err;
  143. err = i2c_smbus_write_word_data(c, reg, val);
  144. if (err)
  145. printk(KERN_INFO "WriteRegPair(%d) failed\n", reg);
  146. return err;
  147. }
  148. static const struct matrox_pll_features maven_pll = {
  149. 50000,
  150. 27000,
  151. 4, 127,
  152. 2, 31,
  153. 3
  154. };
  155. struct matrox_pll_features2 {
  156. unsigned int vco_freq_min;
  157. unsigned int vco_freq_max;
  158. unsigned int feed_div_min;
  159. unsigned int feed_div_max;
  160. unsigned int in_div_min;
  161. unsigned int in_div_max;
  162. unsigned int post_shift_max;
  163. };
  164. struct matrox_pll_ctl {
  165. unsigned int ref_freq;
  166. unsigned int den;
  167. };
  168. static const struct matrox_pll_features2 maven1000_pll = {
  169. 50000000,
  170. 300000000,
  171. 5, 128,
  172. 3, 32,
  173. 3
  174. };
  175. static const struct matrox_pll_ctl maven_PAL = {
  176. 540000,
  177. 50
  178. };
  179. static const struct matrox_pll_ctl maven_NTSC = {
  180. 450450, /* 27027000/60 == 27000000/59.94005994 */
  181. 60
  182. };
  183. static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
  184. const struct matrox_pll_ctl* ctl,
  185. unsigned int htotal, unsigned int vtotal,
  186. unsigned int* in, unsigned int* feed, unsigned int* post,
  187. unsigned int* h2) {
  188. unsigned int besth2 = 0;
  189. unsigned int fxtal = ctl->ref_freq;
  190. unsigned int fmin = pll->vco_freq_min / ctl->den;
  191. unsigned int fwant;
  192. unsigned int p;
  193. unsigned int scrlen;
  194. unsigned int fmax;
  195. DBG(__func__)
  196. scrlen = htotal * (vtotal - 1);
  197. fwant = htotal * vtotal;
  198. fmax = pll->vco_freq_max / ctl->den;
  199. dprintk(KERN_DEBUG "want: %u, xtal: %u, h: %u, v: %u, fmax: %u\n",
  200. fwant, fxtal, htotal, vtotal, fmax);
  201. for (p = 1; p <= pll->post_shift_max; p++) {
  202. if (fwant * 2 > fmax)
  203. break;
  204. fwant *= 2;
  205. }
  206. if (fwant > fmax)
  207. return 0;
  208. for (; p-- > 0; fwant >>= 1) {
  209. unsigned int m;
  210. if (fwant < fmin) break;
  211. for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
  212. unsigned int n;
  213. unsigned int dvd;
  214. unsigned int ln;
  215. n = (fwant * m) / fxtal;
  216. if (n < pll->feed_div_min)
  217. continue;
  218. if (n > pll->feed_div_max)
  219. break;
  220. ln = fxtal * n;
  221. dvd = m << p;
  222. if (ln % dvd)
  223. continue;
  224. ln = ln / dvd;
  225. if (ln < scrlen + 2)
  226. continue;
  227. ln = ln - scrlen;
  228. if (ln > htotal)
  229. continue;
  230. dprintk(KERN_DEBUG "Match: %u / %u / %u / %u\n", n, m, p, ln);
  231. if (ln > besth2) {
  232. dprintk(KERN_DEBUG "Better...\n");
  233. *h2 = besth2 = ln;
  234. *post = p;
  235. *in = m;
  236. *feed = n;
  237. }
  238. }
  239. }
  240. /* if h2/post/in/feed have not been assigned, return zero (error) */
  241. if (besth2 < 2)
  242. return 0;
  243. dprintk(KERN_ERR "clk: %02X %02X %02X %d %d\n", *in, *feed, *post, fxtal, fwant);
  244. return fxtal * (*feed) / (*in) * ctl->den;
  245. }
  246. static unsigned int matroxfb_mavenclock(const struct matrox_pll_ctl* ctl,
  247. unsigned int htotal, unsigned int vtotal,
  248. unsigned int* in, unsigned int* feed, unsigned int* post,
  249. unsigned int* htotal2) {
  250. unsigned int fvco;
  251. unsigned int uninitialized_var(p);
  252. fvco = matroxfb_PLL_mavenclock(&maven1000_pll, ctl, htotal, vtotal, in, feed, &p, htotal2);
  253. if (!fvco)
  254. return -EINVAL;
  255. p = (1 << p) - 1;
  256. if (fvco <= 100000000)
  257. ;
  258. else if (fvco <= 140000000)
  259. p |= 0x08;
  260. else if (fvco <= 180000000)
  261. p |= 0x10;
  262. else
  263. p |= 0x18;
  264. *post = p;
  265. return 0;
  266. }
  267. static void DAC1064_calcclock(unsigned int freq, unsigned int fmax,
  268. unsigned int* in, unsigned int* feed, unsigned int* post) {
  269. unsigned int fvco;
  270. unsigned int p;
  271. fvco = matroxfb_PLL_calcclock(&maven_pll, freq, fmax, in, feed, &p);
  272. p = (1 << p) - 1;
  273. if (fvco <= 100000)
  274. ;
  275. else if (fvco <= 140000)
  276. p |= 0x08;
  277. else if (fvco <= 180000)
  278. p |= 0x10;
  279. else
  280. p |= 0x18;
  281. *post = p;
  282. return;
  283. }
  284. static unsigned char maven_compute_deflicker (const struct maven_data* md) {
  285. unsigned char df;
  286. df = (md->version == MGATVO_B?0x40:0x00);
  287. switch (md->primary_head->altout.tvo_params.deflicker) {
  288. case 0:
  289. /* df |= 0x00; */
  290. break;
  291. case 1:
  292. df |= 0xB1;
  293. break;
  294. case 2:
  295. df |= 0xA2;
  296. break;
  297. }
  298. return df;
  299. }
  300. static void maven_compute_bwlevel (const struct maven_data* md,
  301. int *bl, int *wl) {
  302. const int b = md->primary_head->altout.tvo_params.brightness + BLMIN;
  303. const int c = md->primary_head->altout.tvo_params.contrast;
  304. *bl = max(b - c, BLMIN);
  305. *wl = min(b + c, WLMAX);
  306. }
  307. static const struct maven_gamma* maven_compute_gamma (const struct maven_data* md) {
  308. return maven_gamma + md->primary_head->altout.tvo_params.gamma;
  309. }
  310. static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* data) {
  311. static struct mavenregs palregs = { {
  312. 0x2A, 0x09, 0x8A, 0xCB, /* 00: chroma subcarrier */
  313. 0x00,
  314. 0x00, /* ? not written */
  315. 0x00, /* modified by code (F9 written...) */
  316. 0x00, /* ? not written */
  317. 0x7E, /* 08 */
  318. 0x44, /* 09 */
  319. 0x9C, /* 0A */
  320. 0x2E, /* 0B */
  321. 0x21, /* 0C */
  322. 0x00, /* ? not written */
  323. 0x3F, 0x03, /* 0E-0F */
  324. 0x3F, 0x03, /* 10-11 */
  325. 0x1A, /* 12 */
  326. 0x2A, /* 13 */
  327. 0x1C, 0x3D, 0x14, /* 14-16 */
  328. 0x9C, 0x01, /* 17-18 */
  329. 0x00, /* 19 */
  330. 0xFE, /* 1A */
  331. 0x7E, /* 1B */
  332. 0x60, /* 1C */
  333. 0x05, /* 1D */
  334. 0x89, 0x03, /* 1E-1F */
  335. 0x72, /* 20 */
  336. 0x07, /* 21 */
  337. 0x72, /* 22 */
  338. 0x00, /* 23 */
  339. 0x00, /* 24 */
  340. 0x00, /* 25 */
  341. 0x08, /* 26 */
  342. 0x04, /* 27 */
  343. 0x00, /* 28 */
  344. 0x1A, /* 29 */
  345. 0x55, 0x01, /* 2A-2B */
  346. 0x26, /* 2C */
  347. 0x07, 0x7E, /* 2D-2E */
  348. 0x02, 0x54, /* 2F-30 */
  349. 0xB0, 0x00, /* 31-32 */
  350. 0x14, /* 33 */
  351. 0x49, /* 34 */
  352. 0x00, /* 35 written multiple times */
  353. 0x00, /* 36 not written */
  354. 0xA3, /* 37 */
  355. 0xC8, /* 38 */
  356. 0x22, /* 39 */
  357. 0x02, /* 3A */
  358. 0x22, /* 3B */
  359. 0x3F, 0x03, /* 3C-3D */
  360. 0x00, /* 3E written multiple times */
  361. 0x00, /* 3F not written */
  362. }, MATROXFB_OUTPUT_MODE_PAL, 625, 50 };
  363. static struct mavenregs ntscregs = { {
  364. 0x21, 0xF0, 0x7C, 0x1F, /* 00: chroma subcarrier */
  365. 0x00,
  366. 0x00, /* ? not written */
  367. 0x00, /* modified by code (F9 written...) */
  368. 0x00, /* ? not written */
  369. 0x7E, /* 08 */
  370. 0x43, /* 09 */
  371. 0x7E, /* 0A */
  372. 0x3D, /* 0B */
  373. 0x00, /* 0C */
  374. 0x00, /* ? not written */
  375. 0x41, 0x00, /* 0E-0F */
  376. 0x3C, 0x00, /* 10-11 */
  377. 0x17, /* 12 */
  378. 0x21, /* 13 */
  379. 0x1B, 0x1B, 0x24, /* 14-16 */
  380. 0x83, 0x01, /* 17-18 */
  381. 0x00, /* 19 */
  382. 0x0F, /* 1A */
  383. 0x0F, /* 1B */
  384. 0x60, /* 1C */
  385. 0x05, /* 1D */
  386. 0x89, 0x02, /* 1E-1F */
  387. 0x5F, /* 20 */
  388. 0x04, /* 21 */
  389. 0x5F, /* 22 */
  390. 0x01, /* 23 */
  391. 0x02, /* 24 */
  392. 0x00, /* 25 */
  393. 0x0A, /* 26 */
  394. 0x05, /* 27 */
  395. 0x00, /* 28 */
  396. 0x10, /* 29 */
  397. 0xFF, 0x03, /* 2A-2B */
  398. 0x24, /* 2C */
  399. 0x0F, 0x78, /* 2D-2E */
  400. 0x00, 0x00, /* 2F-30 */
  401. 0xB2, 0x04, /* 31-32 */
  402. 0x14, /* 33 */
  403. 0x02, /* 34 */
  404. 0x00, /* 35 written multiple times */
  405. 0x00, /* 36 not written */
  406. 0xA3, /* 37 */
  407. 0xC8, /* 38 */
  408. 0x15, /* 39 */
  409. 0x05, /* 3A */
  410. 0x3B, /* 3B */
  411. 0x3C, 0x00, /* 3C-3D */
  412. 0x00, /* 3E written multiple times */
  413. 0x00, /* never written */
  414. }, MATROXFB_OUTPUT_MODE_NTSC, 525, 60 };
  415. struct matrox_fb_info *minfo = md->primary_head;
  416. if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_PAL)
  417. *data = palregs;
  418. else
  419. *data = ntscregs;
  420. /* Set deflicker */
  421. data->regs[0x93] = maven_compute_deflicker(md);
  422. /* set gamma */
  423. {
  424. const struct maven_gamma* g;
  425. g = maven_compute_gamma(md);
  426. data->regs[0x83] = g->reg83;
  427. data->regs[0x84] = g->reg84;
  428. data->regs[0x85] = g->reg85;
  429. data->regs[0x86] = g->reg86;
  430. data->regs[0x87] = g->reg87;
  431. data->regs[0x88] = g->reg88;
  432. data->regs[0x89] = g->reg89;
  433. data->regs[0x8A] = g->reg8a;
  434. data->regs[0x8B] = g->reg8b;
  435. }
  436. /* Set contrast / brightness */
  437. {
  438. int bl, wl;
  439. maven_compute_bwlevel (md, &bl, &wl);
  440. data->regs[0x0e] = bl >> 2;
  441. data->regs[0x0f] = bl & 3;
  442. data->regs[0x1e] = wl >> 2;
  443. data->regs[0x1f] = wl & 3;
  444. }
  445. /* Set saturation */
  446. {
  447. data->regs[0x20] =
  448. data->regs[0x22] = minfo->altout.tvo_params.saturation;
  449. }
  450. /* Set HUE */
  451. data->regs[0x25] = minfo->altout.tvo_params.hue;
  452. return;
  453. }
  454. #define LR(x) maven_set_reg(c, (x), m->regs[(x)])
  455. #define LRP(x) maven_set_reg_pair(c, (x), m->regs[(x)] | (m->regs[(x)+1] << 8))
  456. static void maven_init_TV(struct i2c_client* c, const struct mavenregs* m) {
  457. int val;
  458. maven_set_reg(c, 0x3E, 0x01);
  459. maven_get_reg(c, 0x82); /* fetch oscillator state? */
  460. maven_set_reg(c, 0x8C, 0x00);
  461. maven_get_reg(c, 0x94); /* get 0x82 */
  462. maven_set_reg(c, 0x94, 0xA2);
  463. /* xmiscctrl */
  464. maven_set_reg_pair(c, 0x8E, 0x1EFF);
  465. maven_set_reg(c, 0xC6, 0x01);
  466. /* removed code... */
  467. maven_get_reg(c, 0x06);
  468. maven_set_reg(c, 0x06, 0xF9); /* or read |= 0xF0 ? */
  469. /* removed code here... */
  470. /* real code begins here? */
  471. /* chroma subcarrier */
  472. LR(0x00); LR(0x01); LR(0x02); LR(0x03);
  473. LR(0x04);
  474. LR(0x2C);
  475. LR(0x08);
  476. LR(0x0A);
  477. LR(0x09);
  478. LR(0x29);
  479. LRP(0x31);
  480. LRP(0x17);
  481. LR(0x0B);
  482. LR(0x0C);
  483. if (m->mode == MATROXFB_OUTPUT_MODE_PAL) {
  484. maven_set_reg(c, 0x35, 0x10); /* ... */
  485. } else {
  486. maven_set_reg(c, 0x35, 0x0F); /* ... */
  487. }
  488. LRP(0x10);
  489. LRP(0x0E);
  490. LRP(0x1E);
  491. LR(0x20); /* saturation #1 */
  492. LR(0x22); /* saturation #2 */
  493. LR(0x25); /* hue */
  494. LR(0x34);
  495. LR(0x33);
  496. LR(0x19);
  497. LR(0x12);
  498. LR(0x3B);
  499. LR(0x13);
  500. LR(0x39);
  501. LR(0x1D);
  502. LR(0x3A);
  503. LR(0x24);
  504. LR(0x14);
  505. LR(0x15);
  506. LR(0x16);
  507. LRP(0x2D);
  508. LRP(0x2F);
  509. LR(0x1A);
  510. LR(0x1B);
  511. LR(0x1C);
  512. LR(0x23);
  513. LR(0x26);
  514. LR(0x28);
  515. LR(0x27);
  516. LR(0x21);
  517. LRP(0x2A);
  518. if (m->mode == MATROXFB_OUTPUT_MODE_PAL)
  519. maven_set_reg(c, 0x35, 0x1D); /* ... */
  520. else
  521. maven_set_reg(c, 0x35, 0x1C);
  522. LRP(0x3C);
  523. LR(0x37);
  524. LR(0x38);
  525. maven_set_reg(c, 0xB3, 0x01);
  526. maven_get_reg(c, 0xB0); /* read 0x80 */
  527. maven_set_reg(c, 0xB0, 0x08); /* ugh... */
  528. maven_get_reg(c, 0xB9); /* read 0x7C */
  529. maven_set_reg(c, 0xB9, 0x78);
  530. maven_get_reg(c, 0xBF); /* read 0x00 */
  531. maven_set_reg(c, 0xBF, 0x02);
  532. maven_get_reg(c, 0x94); /* read 0x82 */
  533. maven_set_reg(c, 0x94, 0xB3);
  534. LR(0x80); /* 04 1A 91 or 05 21 91 */
  535. LR(0x81);
  536. LR(0x82);
  537. maven_set_reg(c, 0x8C, 0x20);
  538. maven_get_reg(c, 0x8D);
  539. maven_set_reg(c, 0x8D, 0x10);
  540. LR(0x90); /* 4D 50 52 or 4E 05 45 */
  541. LR(0x91);
  542. LR(0x92);
  543. LRP(0x9A); /* 0049 or 004F */
  544. LRP(0x9C); /* 0004 or 0004 */
  545. LRP(0x9E); /* 0458 or 045E */
  546. LRP(0xA0); /* 05DA or 051B */
  547. LRP(0xA2); /* 00CC or 00CF */
  548. LRP(0xA4); /* 007D or 007F */
  549. LRP(0xA6); /* 007C or 007E */
  550. LRP(0xA8); /* 03CB or 03CE */
  551. LRP(0x98); /* 0000 or 0000 */
  552. LRP(0xAE); /* 0044 or 003A */
  553. LRP(0x96); /* 05DA or 051B */
  554. LRP(0xAA); /* 04BC or 046A */
  555. LRP(0xAC); /* 004D or 004E */
  556. LR(0xBE);
  557. LR(0xC2);
  558. maven_get_reg(c, 0x8D);
  559. maven_set_reg(c, 0x8D, 0x04);
  560. LR(0x20); /* saturation #1 */
  561. LR(0x22); /* saturation #2 */
  562. LR(0x93); /* whoops */
  563. LR(0x20); /* oh, saturation #1 again */
  564. LR(0x22); /* oh, saturation #2 again */
  565. LR(0x25); /* hue */
  566. LRP(0x0E);
  567. LRP(0x1E);
  568. LRP(0x0E); /* problems with memory? */
  569. LRP(0x1E); /* yes, matrox must have problems in memory area... */
  570. /* load gamma correction stuff */
  571. LR(0x83);
  572. LR(0x84);
  573. LR(0x85);
  574. LR(0x86);
  575. LR(0x87);
  576. LR(0x88);
  577. LR(0x89);
  578. LR(0x8A);
  579. LR(0x8B);
  580. val = maven_get_reg(c, 0x8D);
  581. val &= 0x14; /* 0x10 or anything ored with it */
  582. maven_set_reg(c, 0x8D, val);
  583. LR(0x33);
  584. LR(0x19);
  585. LR(0x12);
  586. LR(0x3B);
  587. LR(0x13);
  588. LR(0x39);
  589. LR(0x1D);
  590. LR(0x3A);
  591. LR(0x24);
  592. LR(0x14);
  593. LR(0x15);
  594. LR(0x16);
  595. LRP(0x2D);
  596. LRP(0x2F);
  597. LR(0x1A);
  598. LR(0x1B);
  599. LR(0x1C);
  600. LR(0x23);
  601. LR(0x26);
  602. LR(0x28);
  603. LR(0x27);
  604. LR(0x21);
  605. LRP(0x2A);
  606. if (m->mode == MATROXFB_OUTPUT_MODE_PAL)
  607. maven_set_reg(c, 0x35, 0x1D);
  608. else
  609. maven_set_reg(c, 0x35, 0x1C);
  610. LRP(0x3C);
  611. LR(0x37);
  612. LR(0x38);
  613. maven_get_reg(c, 0xB0);
  614. LR(0xB0); /* output mode */
  615. LR(0x90);
  616. LR(0xBE);
  617. LR(0xC2);
  618. LRP(0x9A);
  619. LRP(0xA2);
  620. LRP(0x9E);
  621. LRP(0xA6);
  622. LRP(0xAA);
  623. LRP(0xAC);
  624. maven_set_reg(c, 0x3E, 0x00);
  625. maven_set_reg(c, 0x95, 0x20);
  626. }
  627. static int maven_find_exact_clocks(unsigned int ht, unsigned int vt,
  628. struct mavenregs* m) {
  629. unsigned int x;
  630. unsigned int err = ~0;
  631. /* 1:1 */
  632. m->regs[0x80] = 0x0F;
  633. m->regs[0x81] = 0x07;
  634. m->regs[0x82] = 0x81;
  635. for (x = 0; x < 8; x++) {
  636. unsigned int c;
  637. unsigned int uninitialized_var(a), uninitialized_var(b),
  638. uninitialized_var(h2);
  639. unsigned int h = ht + 2 + x;
  640. if (!matroxfb_mavenclock((m->mode == MATROXFB_OUTPUT_MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) {
  641. unsigned int diff = h - h2;
  642. if (diff < err) {
  643. err = diff;
  644. m->regs[0x80] = a - 1;
  645. m->regs[0x81] = b - 1;
  646. m->regs[0x82] = c | 0x80;
  647. m->hcorr = h2 - 2;
  648. m->htotal = h - 2;
  649. }
  650. }
  651. }
  652. return err != ~0U;
  653. }
  654. static inline int maven_compute_timming(struct maven_data* md,
  655. struct my_timming* mt,
  656. struct mavenregs* m) {
  657. unsigned int tmpi;
  658. unsigned int a, bv, c;
  659. struct matrox_fb_info *minfo = md->primary_head;
  660. m->mode = minfo->outputs[1].mode;
  661. if (m->mode != MATROXFB_OUTPUT_MODE_MONITOR) {
  662. unsigned int lmargin;
  663. unsigned int umargin;
  664. unsigned int vslen;
  665. unsigned int hcrt;
  666. unsigned int slen;
  667. maven_init_TVdata(md, m);
  668. if (maven_find_exact_clocks(mt->HTotal, mt->VTotal, m) == 0)
  669. return -EINVAL;
  670. lmargin = mt->HTotal - mt->HSyncEnd;
  671. slen = mt->HSyncEnd - mt->HSyncStart;
  672. hcrt = mt->HTotal - slen - mt->delay;
  673. umargin = mt->VTotal - mt->VSyncEnd;
  674. vslen = mt->VSyncEnd - mt->VSyncStart;
  675. if (m->hcorr < mt->HTotal)
  676. hcrt += m->hcorr;
  677. if (hcrt > mt->HTotal)
  678. hcrt -= mt->HTotal;
  679. if (hcrt + 2 > mt->HTotal)
  680. hcrt = 0; /* or issue warning? */
  681. /* last (first? middle?) line in picture can have different length */
  682. /* hlen - 2 */
  683. m->regs[0x96] = m->hcorr;
  684. m->regs[0x97] = m->hcorr >> 8;
  685. /* ... */
  686. m->regs[0x98] = 0x00; m->regs[0x99] = 0x00;
  687. /* hblanking end */
  688. m->regs[0x9A] = lmargin; /* 100% */
  689. m->regs[0x9B] = lmargin >> 8; /* 100% */
  690. /* who knows */
  691. m->regs[0x9C] = 0x04;
  692. m->regs[0x9D] = 0x00;
  693. /* htotal - 2 */
  694. m->regs[0xA0] = m->htotal;
  695. m->regs[0xA1] = m->htotal >> 8;
  696. /* vblanking end */
  697. m->regs[0xA2] = mt->VTotal - mt->VSyncStart - 1; /* stop vblanking */
  698. m->regs[0xA3] = (mt->VTotal - mt->VSyncStart - 1) >> 8;
  699. /* something end... [A6]+1..[A8] */
  700. if (md->version == MGATVO_B) {
  701. m->regs[0xA4] = 0x04;
  702. m->regs[0xA5] = 0x00;
  703. } else {
  704. m->regs[0xA4] = 0x01;
  705. m->regs[0xA5] = 0x00;
  706. }
  707. /* something start... 0..[A4]-1 */
  708. m->regs[0xA6] = 0x00;
  709. m->regs[0xA7] = 0x00;
  710. /* vertical line count - 1 */
  711. m->regs[0xA8] = mt->VTotal - 1;
  712. m->regs[0xA9] = (mt->VTotal - 1) >> 8;
  713. /* horizontal vidrst pos */
  714. m->regs[0xAA] = hcrt; /* 0 <= hcrt <= htotal - 2 */
  715. m->regs[0xAB] = hcrt >> 8;
  716. /* vertical vidrst pos */
  717. m->regs[0xAC] = mt->VTotal - 2;
  718. m->regs[0xAD] = (mt->VTotal - 2) >> 8;
  719. /* moves picture up/down and so on... */
  720. m->regs[0xAE] = 0x01; /* Fix this... 0..VTotal */
  721. m->regs[0xAF] = 0x00;
  722. {
  723. int hdec;
  724. int hlen;
  725. unsigned int ibmin = 4 + lmargin + mt->HDisplay;
  726. unsigned int ib;
  727. int i;
  728. /* Verify! */
  729. /* Where 94208 came from? */
  730. if (mt->HTotal)
  731. hdec = 94208 / (mt->HTotal);
  732. else
  733. hdec = 0x81;
  734. if (hdec > 0x81)
  735. hdec = 0x81;
  736. if (hdec < 0x41)
  737. hdec = 0x41;
  738. hdec--;
  739. hlen = 98304 - 128 - ((lmargin + mt->HDisplay - 8) * hdec);
  740. if (hlen < 0)
  741. hlen = 0;
  742. hlen = hlen >> 8;
  743. if (hlen > 0xFF)
  744. hlen = 0xFF;
  745. /* Now we have to compute input buffer length.
  746. If you want any picture, it must be between
  747. 4 + lmargin + xres
  748. and
  749. 94208 / hdec
  750. If you want perfect picture even on the top
  751. of screen, it must be also
  752. 0x3C0000 * i / hdec + Q - R / hdec
  753. where
  754. R Qmin Qmax
  755. 0x07000 0x5AE 0x5BF
  756. 0x08000 0x5CF 0x5FF
  757. 0x0C000 0x653 0x67F
  758. 0x10000 0x6F8 0x6FF
  759. */
  760. i = 1;
  761. do {
  762. ib = ((0x3C0000 * i - 0x8000)/ hdec + 0x05E7) >> 8;
  763. i++;
  764. } while (ib < ibmin);
  765. if (ib >= m->htotal + 2) {
  766. ib = ibmin;
  767. }
  768. m->regs[0x90] = hdec; /* < 0x40 || > 0x80 is bad... 0x80 is questionable */
  769. m->regs[0xC2] = hlen;
  770. /* 'valid' input line length */
  771. m->regs[0x9E] = ib;
  772. m->regs[0x9F] = ib >> 8;
  773. }
  774. {
  775. int vdec;
  776. int vlen;
  777. #define MATROX_USE64BIT_DIVIDE
  778. if (mt->VTotal) {
  779. #ifdef MATROX_USE64BIT_DIVIDE
  780. u64 f1;
  781. u32 a;
  782. u32 b;
  783. a = m->vlines * (m->htotal + 2);
  784. b = (mt->VTotal - 1) * (m->htotal + 2) + m->hcorr + 2;
  785. f1 = ((u64)a) << 15; /* *32768 */
  786. do_div(f1, b);
  787. vdec = f1;
  788. #else
  789. vdec = m->vlines * 32768 / mt->VTotal;
  790. #endif
  791. } else
  792. vdec = 0x8000;
  793. if (vdec > 0x8000)
  794. vdec = 0x8000;
  795. vlen = (vslen + umargin + mt->VDisplay) * vdec;
  796. vlen = (vlen >> 16) - 146; /* FIXME: 146?! */
  797. if (vlen < 0)
  798. vlen = 0;
  799. if (vlen > 0xFF)
  800. vlen = 0xFF;
  801. vdec--;
  802. m->regs[0x91] = vdec;
  803. m->regs[0x92] = vdec >> 8;
  804. m->regs[0xBE] = vlen;
  805. }
  806. m->regs[0xB0] = 0x08; /* output: SVideo/Composite */
  807. return 0;
  808. }
  809. DAC1064_calcclock(mt->pixclock, 450000, &a, &bv, &c);
  810. m->regs[0x80] = a;
  811. m->regs[0x81] = bv;
  812. m->regs[0x82] = c | 0x80;
  813. m->regs[0xB3] = 0x01;
  814. m->regs[0x94] = 0xB2;
  815. /* htotal... */
  816. m->regs[0x96] = mt->HTotal;
  817. m->regs[0x97] = mt->HTotal >> 8;
  818. /* ?? */
  819. m->regs[0x98] = 0x00;
  820. m->regs[0x99] = 0x00;
  821. /* hsync len */
  822. tmpi = mt->HSyncEnd - mt->HSyncStart;
  823. m->regs[0x9A] = tmpi;
  824. m->regs[0x9B] = tmpi >> 8;
  825. /* hblank end */
  826. tmpi = mt->HTotal - mt->HSyncStart;
  827. m->regs[0x9C] = tmpi;
  828. m->regs[0x9D] = tmpi >> 8;
  829. /* hblank start */
  830. tmpi += mt->HDisplay;
  831. m->regs[0x9E] = tmpi;
  832. m->regs[0x9F] = tmpi >> 8;
  833. /* htotal + 1 */
  834. tmpi = mt->HTotal + 1;
  835. m->regs[0xA0] = tmpi;
  836. m->regs[0xA1] = tmpi >> 8;
  837. /* vsync?! */
  838. tmpi = mt->VSyncEnd - mt->VSyncStart - 1;
  839. m->regs[0xA2] = tmpi;
  840. m->regs[0xA3] = tmpi >> 8;
  841. /* ignored? */
  842. tmpi = mt->VTotal - mt->VSyncStart;
  843. m->regs[0xA4] = tmpi;
  844. m->regs[0xA5] = tmpi >> 8;
  845. /* ignored? */
  846. tmpi = mt->VTotal - 1;
  847. m->regs[0xA6] = tmpi;
  848. m->regs[0xA7] = tmpi >> 8;
  849. /* vtotal - 1 */
  850. m->regs[0xA8] = tmpi;
  851. m->regs[0xA9] = tmpi >> 8;
  852. /* hor vidrst */
  853. tmpi = mt->HTotal - mt->delay;
  854. m->regs[0xAA] = tmpi;
  855. m->regs[0xAB] = tmpi >> 8;
  856. /* vert vidrst */
  857. tmpi = mt->VTotal - 2;
  858. m->regs[0xAC] = tmpi;
  859. m->regs[0xAD] = tmpi >> 8;
  860. /* ignored? */
  861. m->regs[0xAE] = 0x00;
  862. m->regs[0xAF] = 0x00;
  863. m->regs[0xB0] = 0x03; /* output: monitor */
  864. m->regs[0xB1] = 0xA0; /* ??? */
  865. m->regs[0x8C] = 0x20; /* must be set... */
  866. m->regs[0x8D] = 0x04; /* defaults to 0x10: test signal */
  867. m->regs[0xB9] = 0x1A; /* defaults to 0x2C: too bright */
  868. m->regs[0xBF] = 0x22; /* makes picture stable */
  869. return 0;
  870. }
  871. static int maven_program_timming(struct maven_data* md,
  872. const struct mavenregs* m) {
  873. struct i2c_client *c = md->client;
  874. if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) {
  875. LR(0x80);
  876. LR(0x81);
  877. LR(0x82);
  878. LR(0xB3);
  879. LR(0x94);
  880. LRP(0x96);
  881. LRP(0x98);
  882. LRP(0x9A);
  883. LRP(0x9C);
  884. LRP(0x9E);
  885. LRP(0xA0);
  886. LRP(0xA2);
  887. LRP(0xA4);
  888. LRP(0xA6);
  889. LRP(0xA8);
  890. LRP(0xAA);
  891. LRP(0xAC);
  892. LRP(0xAE);
  893. LR(0xB0); /* output: monitor */
  894. LR(0xB1); /* ??? */
  895. LR(0x8C); /* must be set... */
  896. LR(0x8D); /* defaults to 0x10: test signal */
  897. LR(0xB9); /* defaults to 0x2C: too bright */
  898. LR(0xBF); /* makes picture stable */
  899. } else {
  900. maven_init_TV(c, m);
  901. }
  902. return 0;
  903. }
  904. static inline int maven_resync(struct maven_data* md) {
  905. struct i2c_client *c = md->client;
  906. maven_set_reg(c, 0x95, 0x20); /* start whole thing */
  907. return 0;
  908. }
  909. static int maven_get_queryctrl (struct maven_data* md,
  910. struct v4l2_queryctrl *p) {
  911. int i;
  912. i = get_ctrl_id(p->id);
  913. if (i >= 0) {
  914. *p = maven_controls[i].desc;
  915. return 0;
  916. }
  917. if (i == -ENOENT) {
  918. static const struct v4l2_queryctrl disctrl =
  919. { .flags = V4L2_CTRL_FLAG_DISABLED };
  920. i = p->id;
  921. *p = disctrl;
  922. p->id = i;
  923. sprintf(p->name, "Ctrl #%08X", i);
  924. return 0;
  925. }
  926. return -EINVAL;
  927. }
  928. static int maven_set_control (struct maven_data* md,
  929. struct v4l2_control *p) {
  930. int i;
  931. i = get_ctrl_id(p->id);
  932. if (i < 0) return -EINVAL;
  933. /*
  934. * Check if changed.
  935. */
  936. if (p->value == *get_ctrl_ptr(md, i)) return 0;
  937. /*
  938. * Check limits.
  939. */
  940. if (p->value > maven_controls[i].desc.maximum) return -EINVAL;
  941. if (p->value < maven_controls[i].desc.minimum) return -EINVAL;
  942. /*
  943. * Store new value.
  944. */
  945. *get_ctrl_ptr(md, i) = p->value;
  946. switch (p->id) {
  947. case V4L2_CID_BRIGHTNESS:
  948. case V4L2_CID_CONTRAST:
  949. {
  950. int blacklevel, whitelevel;
  951. maven_compute_bwlevel(md, &blacklevel, &whitelevel);
  952. blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8);
  953. whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8);
  954. maven_set_reg_pair(md->client, 0x0e, blacklevel);
  955. maven_set_reg_pair(md->client, 0x1e, whitelevel);
  956. }
  957. break;
  958. case V4L2_CID_SATURATION:
  959. {
  960. maven_set_reg(md->client, 0x20, p->value);
  961. maven_set_reg(md->client, 0x22, p->value);
  962. }
  963. break;
  964. case V4L2_CID_HUE:
  965. {
  966. maven_set_reg(md->client, 0x25, p->value);
  967. }
  968. break;
  969. case V4L2_CID_GAMMA:
  970. {
  971. const struct maven_gamma* g;
  972. g = maven_compute_gamma(md);
  973. maven_set_reg(md->client, 0x83, g->reg83);
  974. maven_set_reg(md->client, 0x84, g->reg84);
  975. maven_set_reg(md->client, 0x85, g->reg85);
  976. maven_set_reg(md->client, 0x86, g->reg86);
  977. maven_set_reg(md->client, 0x87, g->reg87);
  978. maven_set_reg(md->client, 0x88, g->reg88);
  979. maven_set_reg(md->client, 0x89, g->reg89);
  980. maven_set_reg(md->client, 0x8a, g->reg8a);
  981. maven_set_reg(md->client, 0x8b, g->reg8b);
  982. }
  983. break;
  984. case MATROXFB_CID_TESTOUT:
  985. {
  986. unsigned char val
  987. = maven_get_reg(md->client, 0x8d);
  988. if (p->value) val |= 0x10;
  989. else val &= ~0x10;
  990. maven_set_reg(md->client, 0x8d, val);
  991. }
  992. break;
  993. case MATROXFB_CID_DEFLICKER:
  994. {
  995. maven_set_reg(md->client, 0x93, maven_compute_deflicker(md));
  996. }
  997. break;
  998. }
  999. return 0;
  1000. }
  1001. static int maven_get_control (struct maven_data* md,
  1002. struct v4l2_control *p) {
  1003. int i;
  1004. i = get_ctrl_id(p->id);
  1005. if (i < 0) return -EINVAL;
  1006. p->value = *get_ctrl_ptr(md, i);
  1007. return 0;
  1008. }
  1009. /******************************************************/
  1010. static int maven_out_compute(void* md, struct my_timming* mt) {
  1011. #define mdinfo ((struct maven_data*)md)
  1012. #define minfo (mdinfo->primary_head)
  1013. return maven_compute_timming(md, mt, &minfo->hw.maven);
  1014. #undef minfo
  1015. #undef mdinfo
  1016. }
  1017. static int maven_out_program(void* md) {
  1018. #define mdinfo ((struct maven_data*)md)
  1019. #define minfo (mdinfo->primary_head)
  1020. return maven_program_timming(md, &minfo->hw.maven);
  1021. #undef minfo
  1022. #undef mdinfo
  1023. }
  1024. static int maven_out_start(void* md) {
  1025. return maven_resync(md);
  1026. }
  1027. static int maven_out_verify_mode(void* md, u_int32_t arg) {
  1028. switch (arg) {
  1029. case MATROXFB_OUTPUT_MODE_PAL:
  1030. case MATROXFB_OUTPUT_MODE_NTSC:
  1031. case MATROXFB_OUTPUT_MODE_MONITOR:
  1032. return 0;
  1033. }
  1034. return -EINVAL;
  1035. }
  1036. static int maven_out_get_queryctrl(void* md, struct v4l2_queryctrl* p) {
  1037. return maven_get_queryctrl(md, p);
  1038. }
  1039. static int maven_out_get_ctrl(void* md, struct v4l2_control* p) {
  1040. return maven_get_control(md, p);
  1041. }
  1042. static int maven_out_set_ctrl(void* md, struct v4l2_control* p) {
  1043. return maven_set_control(md, p);
  1044. }
  1045. static struct matrox_altout maven_altout = {
  1046. .name = "Secondary output",
  1047. .compute = maven_out_compute,
  1048. .program = maven_out_program,
  1049. .start = maven_out_start,
  1050. .verifymode = maven_out_verify_mode,
  1051. .getqueryctrl = maven_out_get_queryctrl,
  1052. .getctrl = maven_out_get_ctrl,
  1053. .setctrl = maven_out_set_ctrl,
  1054. };
  1055. static int maven_init_client(struct i2c_client* clnt) {
  1056. struct maven_data* md = i2c_get_clientdata(clnt);
  1057. struct matrox_fb_info *minfo = container_of(clnt->adapter,
  1058. struct i2c_bit_adapter,
  1059. adapter)->minfo;
  1060. md->primary_head = minfo;
  1061. md->client = clnt;
  1062. down_write(&minfo->altout.lock);
  1063. minfo->outputs[1].output = &maven_altout;
  1064. minfo->outputs[1].src = minfo->outputs[1].default_src;
  1065. minfo->outputs[1].data = md;
  1066. minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
  1067. up_write(&minfo->altout.lock);
  1068. if (maven_get_reg(clnt, 0xB2) < 0x14) {
  1069. md->version = MGATVO_B;
  1070. /* Tweak some things for this old chip */
  1071. } else {
  1072. md->version = MGATVO_C;
  1073. }
  1074. /*
  1075. * Set all parameters to its initial values.
  1076. */
  1077. {
  1078. unsigned int i;
  1079. for (i = 0; i < MAVCTRLS; ++i) {
  1080. *get_ctrl_ptr(md, i) = maven_controls[i].desc.default_value;
  1081. }
  1082. }
  1083. return 0;
  1084. }
  1085. static int maven_shutdown_client(struct i2c_client* clnt) {
  1086. struct maven_data* md = i2c_get_clientdata(clnt);
  1087. if (md->primary_head) {
  1088. struct matrox_fb_info *minfo = md->primary_head;
  1089. down_write(&minfo->altout.lock);
  1090. minfo->outputs[1].src = MATROXFB_SRC_NONE;
  1091. minfo->outputs[1].output = NULL;
  1092. minfo->outputs[1].data = NULL;
  1093. minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
  1094. up_write(&minfo->altout.lock);
  1095. md->primary_head = NULL;
  1096. }
  1097. return 0;
  1098. }
  1099. static int maven_probe(struct i2c_client *client,
  1100. const struct i2c_device_id *id)
  1101. {
  1102. struct i2c_adapter *adapter = client->adapter;
  1103. int err = -ENODEV;
  1104. struct maven_data* data;
  1105. if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA |
  1106. I2C_FUNC_SMBUS_BYTE_DATA |
  1107. I2C_FUNC_PROTOCOL_MANGLING))
  1108. goto ERROR0;
  1109. if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
  1110. err = -ENOMEM;
  1111. goto ERROR0;
  1112. }
  1113. i2c_set_clientdata(client, data);
  1114. err = maven_init_client(client);
  1115. if (err)
  1116. goto ERROR4;
  1117. return 0;
  1118. ERROR4:;
  1119. kfree(data);
  1120. ERROR0:;
  1121. return err;
  1122. }
  1123. static int maven_remove(struct i2c_client *client)
  1124. {
  1125. maven_shutdown_client(client);
  1126. kfree(i2c_get_clientdata(client));
  1127. return 0;
  1128. }
  1129. static const struct i2c_device_id maven_id[] = {
  1130. { "maven", 0 },
  1131. { }
  1132. };
  1133. MODULE_DEVICE_TABLE(i2c, maven_id);
  1134. static struct i2c_driver maven_driver={
  1135. .driver = {
  1136. .name = "maven",
  1137. },
  1138. .probe = maven_probe,
  1139. .remove = maven_remove,
  1140. .id_table = maven_id,
  1141. };
  1142. static int __init matroxfb_maven_init(void)
  1143. {
  1144. return i2c_add_driver(&maven_driver);
  1145. }
  1146. static void __exit matroxfb_maven_exit(void)
  1147. {
  1148. i2c_del_driver(&maven_driver);
  1149. }
  1150. MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
  1151. MODULE_DESCRIPTION("Matrox G200/G400 Matrox MGA-TVO driver");
  1152. MODULE_LICENSE("GPL");
  1153. module_init(matroxfb_maven_init);
  1154. module_exit(matroxfb_maven_exit);
  1155. /* we do not have __setup() yet */