ks0127.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:24k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /*
  2.  * for the Matrox Marvel G200 and Rainbow Runner-G series
  3.  *
  4.  * This module is an interface to the KS0127 video decoder chip.
  5.  *
  6.  * Copyright (C) 1999  Ryan Drake <stiletto@mediaone.net>
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License
  10.  * as published by the Free Software Foundation; either version 2
  11.  * of the License, or (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21.  *
  22.  *
  23.  *****************************************************************************
  24.  * Version History:
  25.  * V1.0 Ryan Drake    Initial version by Ryan Drake
  26.  * V1.1 Gerard v.d. Horst  Added some debugoutput, reset the video-standard
  27.  */
  28. #ifndef __KERNEL__
  29. #define __KERNEL__
  30. #endif
  31. #ifndef MODULE
  32. #define MODULE
  33. #endif
  34. #include <linux/module.h>
  35. #include <linux/delay.h>
  36. #include <linux/errno.h>
  37. #include <linux/kernel.h>
  38. #include <linux/malloc.h>
  39. #include <linux/i2c.h>
  40. #include "ks0127.h"
  41. #define dprintk     if (debug) printk
  42. static int debug = 0; /* insmod parameter */
  43. #if LINUX_VERSION_CODE >= 0x020100
  44. MODULE_PARM(debug,"i");
  45. #endif
  46. #define KS0127_DEVNAME  "ks0127"
  47. /* i2c identification */
  48. #define I2C_KS0127_ADDON   0xD8
  49. #define I2C_KS0127_ONBOARD 0xDA
  50. /* ks0127 control registers */
  51. #define KS_STAT     0x00
  52. #define KS_CMDA     0x01
  53. #define KS_CMDB     0x02
  54. #define KS_CMDC     0x03
  55. #define KS_CMDD     0x04
  56. #define KS_HAVB     0x05
  57. #define KS_HAVE     0x06
  58. #define KS_HS1B     0x07
  59. #define KS_HS1E     0x08
  60. #define KS_HS2B     0x09
  61. #define KS_HS2E     0x0a
  62. #define KS_AGC      0x0b
  63. #define KS_HXTRA    0x0c
  64. #define KS_CMDE     0x0d
  65. #define KS_PORTAB   0x0e
  66. #define KS_LUMA     0x0f
  67. #define KS_CON      0x10
  68. #define KS_BRT      0x11
  69. #define KS_CHROMA   0x12
  70. #define KS_CHROMB   0x13
  71. #define KS_DEMOD    0x14
  72. #define KS_SAT      0x15
  73. #define KS_HUE      0x16
  74. #define KS_VERTIA   0x17
  75. #define KS_VERTIB   0x18
  76. #define KS_VERTIC   0x19
  77. #define KS_HSCLL    0x1a
  78. #define KS_HSCLH    0x1b
  79. #define KS_VSCLL    0x1c
  80. #define KS_VSCLH    0x1d
  81. #define KS_OFMTA    0x1e
  82. #define KS_OFMTB    0x1f
  83. #define KS_VBICTL   0x20
  84. #define KS_CCDAT2   0x21
  85. #define KS_CCDAT1   0x22
  86. #define KS_VBIL30   0x23
  87. #define KS_VBIL74   0x24
  88. #define KS_VBIL118  0x25
  89. #define KS_VBIL1512 0x26
  90. #define KS_TTFRAM   0x27
  91. #define KS_TESTA    0x28
  92. #define KS_UVOFFH   0x29
  93. #define KS_UVOFFL   0x2a
  94. #define KS_UGAIN    0x2b
  95. #define KS_VGAIN    0x2c
  96. #define KS_VAVB     0x2d
  97. #define KS_VAVE     0x2e
  98. #define KS_CTRACK   0x2f
  99. #define KS_POLCTL   0x30
  100. #define KS_REFCOD   0x31
  101. #define KS_INVALY   0x32
  102. #define KS_INVALU   0x33
  103. #define KS_INVALV   0x34
  104. #define KS_UNUSEY   0x35
  105. #define KS_UNUSEU   0x36
  106. #define KS_UNUSEV   0x37
  107. #define KS_USRSAV   0x38
  108. #define KS_USREAV   0x39
  109. #define KS_SHS1A    0x3a
  110. #define KS_SHS1B    0x3b
  111. #define KS_SHS1C    0x3c
  112. #define KS_CMDE2    0x3d
  113. #define KS_VSDEL    0x3e
  114. #define KS_CMDF     0x3f
  115. #define KS_GAMMA0   0x40
  116. #define KS_GAMMA1   0x41
  117. #define KS_GAMMA2   0x42
  118. #define KS_GAMMA3   0x43
  119. #define KS_GAMMA4   0x44
  120. #define KS_GAMMA5   0x45
  121. #define KS_GAMMA6   0x46
  122. #define KS_GAMMA7   0x47
  123. #define KS_GAMMA8   0x48
  124. #define KS_GAMMA9   0x49
  125. #define KS_GAMMA10  0x4a
  126. #define KS_GAMMA11  0x4b
  127. #define KS_GAMMA12  0x4c
  128. #define KS_GAMMA13  0x4d
  129. #define KS_GAMMA14  0x4e
  130. #define KS_GAMMA15  0x4f
  131. #define KS_GAMMA16  0x50
  132. #define KS_GAMMA17  0x51
  133. #define KS_GAMMA18  0x52
  134. #define KS_GAMMA19  0x53
  135. #define KS_GAMMA20  0x54
  136. #define KS_GAMMA21  0x55
  137. #define KS_GAMMA22  0x56
  138. #define KS_GAMMA23  0x57
  139. #define KS_GAMMA24  0x58
  140. #define KS_GAMMA25  0x59
  141. #define KS_GAMMA26  0x5a
  142. #define KS_GAMMA27  0x5b
  143. #define KS_GAMMA28  0x5c
  144. #define KS_GAMMA29  0x5d
  145. #define KS_GAMMA30  0x5e
  146. #define KS_GAMMA31  0x5f
  147. #define KS_GAMMAD0  0x60
  148. #define KS_GAMMAD1  0x61
  149. #define KS_GAMMAD2  0x62
  150. #define KS_GAMMAD3  0x63
  151. #define KS_GAMMAD4  0x64
  152. #define KS_GAMMAD5  0x65
  153. #define KS_GAMMAD6  0x66
  154. #define KS_GAMMAD7  0x67
  155. #define KS_GAMMAD8  0x68
  156. #define KS_GAMMAD9  0x69
  157. #define KS_GAMMAD10 0x6a
  158. #define KS_GAMMAD11 0x6b
  159. #define KS_GAMMAD12 0x6c
  160. #define KS_GAMMAD13 0x6d
  161. #define KS_GAMMAD14 0x6e
  162. #define KS_GAMMAD15 0x6f
  163. #define KS_GAMMAD16 0x70
  164. #define KS_GAMMAD17 0x71
  165. #define KS_GAMMAD18 0x72
  166. #define KS_GAMMAD19 0x73
  167. #define KS_GAMMAD20 0x74
  168. #define KS_GAMMAD21 0x75
  169. #define KS_GAMMAD22 0x76
  170. #define KS_GAMMAD23 0x77
  171. #define KS_GAMMAD24 0x78
  172. #define KS_GAMMAD25 0x79
  173. #define KS_GAMMAD26 0x7a
  174. #define KS_GAMMAD27 0x7b
  175. #define KS_GAMMAD28 0x7c
  176. #define KS_GAMMAD29 0x7d
  177. #define KS_GAMMAD30 0x7e
  178. #define KS_GAMMAD31 0x7f
  179. /****************************************************************************
  180. * mga_dev : represents one ks0127 chip.
  181. ****************************************************************************/
  182. struct ks0127 {
  183. struct i2c_bus* bus;
  184.         unsigned char addr;
  185. int format_width;
  186. int format_height;
  187. int cap_width;
  188. int cap_height;
  189. };
  190. /****************************************************************************
  191. * raw register access : these routines directly interact with the ks0127's
  192. *                       registers via the i2c
  193. ****************************************************************************/
  194. #define I2C_SET(bus,ctrl,data)  (bus->i2c_setlines(bus,ctrl,data))
  195. #define I2C_GET(bus)            (bus->i2c_getdataline(bus))
  196. /* We need to manually read because of a bug in the KS0127 chip.
  197.  *
  198.  * An explanation from kayork@mail.utexas.edu:
  199.  *
  200.  * During I2C reads, the KS0127 only samples for a stop condition
  201.  * during the place where the acknoledge bit should be. Any standard
  202.  * I2C implementation (correctly) throws in another clock transition
  203.  * at the 9th bit, and the KS0127 will not recognize the stop condition
  204.  * and will continue to clock out data.
  205.  *
  206.  * So we have to do the read ourself.  Big deal.
  207.  */
  208. static u8 ks0127_read( struct ks0127* ks, u8 reg )
  209. {
  210. char val = 0;
  211.         int i;
  212. LOCK_FLAGS;
  213. LOCK_I2C_BUS( ks->bus );
  214.         i2c_write( ks->bus, ks->addr, reg, 0, 0 );
  215.         i2c_start( ks->bus );
  216.         i2c_sendbyte( ks->bus, ks->addr | 1, 0 );
  217.         I2C_SET(ks->bus,0,1);
  218.         for (i=7; i>=0; i--) {
  219.                 I2C_SET(ks->bus,1,1);
  220.                 if (I2C_GET(ks->bus))
  221.                         val |= (1<<i);
  222.                 I2C_SET(ks->bus,0,1);
  223.         }
  224.         /* no ack! */
  225.         i2c_stop( ks->bus );
  226.                         
  227.         UNLOCK_I2C_BUS( ks->bus );
  228.         return val;
  229. }
  230. static void ks0127_write( struct ks0127* ks, u8 reg, u8 val )
  231. {
  232. LOCK_FLAGS;
  233. LOCK_I2C_BUS( ks->bus );
  234.         i2c_write( ks->bus, ks->addr, reg, val, 1 );
  235.         UNLOCK_I2C_BUS( ks->bus );
  236. }
  237. /* generic bit-twiddling */
  238. static void ks0127_and_or( struct ks0127* ks, u8 reg, u8 and_v, u8 or_v )
  239. {
  240.         u8 val = ks0127_read( ks, reg );
  241.         val = (val & and_v) | or_v;
  242.         ks0127_write( ks, reg, val );
  243. }
  244. static int ks0127_probe( struct ks0127* ks )
  245. {
  246.         int ack;
  247. LOCK_FLAGS;
  248. LOCK_I2C_BUS( ks->bus );
  249. ack = i2c_sendbyte( ks->bus, ks->addr, 2000 );
  250. UNLOCK_I2C_BUS( ks->bus );
  251.         return ack;
  252. }
  253. /****************************************************************************
  254. * ks0127 private api
  255. ****************************************************************************/
  256. static void ks0127_reset( struct ks0127* ks )
  257. {
  258.         int i;
  259.         static u8 table[] =
  260.         {
  261. /* 00 */        0x97,0x0c,0x02,0x42,0x01,0x0c,0x04,0x0c,
  262. /* 08 */        0x00,0x00,0x00,0x53,0x00,0x00,0x0f,0x02,
  263. /* 10 */        0x00,0x00,0x2a,0x00,0x80,0x00,0x00,0x60,
  264. #ifdef NEVER
  265. /* 18 */        0x14,0x48,0x01,0x00,0x00,0x00,0x20,0x00,
  266. #else
  267. /* 18 */        0x10,0x4b,0x01,0x00,0x00,0x00,0x20,0x00,
  268. #endif
  269. /* 20 */        0xfd,0x00,0x00,0xa8,0xaa,0x2a,0x00,0x00,
  270. #ifdef NEVER
  271. /* 28 */        0x09,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
  272. #else
  273. /* 28 */        0x09,0x00,0x00,0x00,0x00,0x13,0x7c,0x00,
  274. #endif
  275. /* 30 */        0x41,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,
  276. /* 38 */        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06
  277.         };
  278. dprintk( "ks0127: resetn" );
  279.         udelay(1000);
  280.         /* initialize all registers to known values (except STAT which is ro) */
  281.         for( i=1; i<sizeof(table); i++ )
  282.                 ks0127_write( ks, i, table[i] );
  283. //        ks0127_and_or( ks, KS_OFMTA,  0xef, 0x20 );
  284. //        ks0127_and_or( ks, KS_PORTAB, 0xff, 0x0f );
  285. //        ks0127_and_or( ks, KS_CMDD,   0xff, 0x01 );
  286. }
  287. /****************************************************************************
  288. * ks0127 i2c driver interface
  289. ****************************************************************************/
  290. static int ks0127_attach( struct i2c_device* device )
  291. {
  292. struct ks0127* ks;
  293. device->data = ks = kmalloc( sizeof( *ks ), GFP_KERNEL );
  294. if( ks == NULL )
  295. return -ENOMEM;
  296. memset( ks, 0, sizeof( *ks ) );
  297.         strcpy( device->name, KS0127_DEVNAME );
  298. ks->bus = device->bus;
  299. ks->addr = device->addr;
  300.         /* probe the device to determine who it is */
  301.         if( !ks0127_probe( ks ) )
  302.         {
  303.                 /* nobody home */
  304.                 kfree( ks );
  305.                 return -1;
  306.         }
  307.         /* reset the device */
  308.         ks0127_reset( ks );
  309. #ifdef NEVER
  310. printk(KERN_INFO "ks0127: attach: %s video decodern", ks->addr==I2C_KS0127_ADDON?"addon":"on-board" );
  311. #endif
  312.         MOD_INC_USE_COUNT;
  313. return 0;
  314. }
  315. static int ks0127_detach(struct i2c_device* device)
  316. {
  317. struct ks0127* ks = (struct ks0127*)device->data;
  318. ks0127_reset( ks );
  319. kfree( ks );
  320. dprintk( "ks0127: detachn" );
  321. MOD_DEC_USE_COUNT;
  322. return 0;
  323. }
  324. void ks0127_getcrop(struct ks0127 *ks, int *xstart, int *xend, int *ystart, int *yend)
  325. {
  326. *xstart = ((ks0127_read(ks, KS_HXTRA) & 0xe0) << 3) + 
  327. ks0127_read(ks, KS_HAVB);
  328. *xend = ((ks0127_read(ks, KS_HXTRA) & 0x1c) << 6) + 
  329. ks0127_read(ks, KS_HAVE);
  330. if ((*xstart) & 0x400) 
  331. *xstart |= ~0x3ff;
  332. if ((*xend) & 0x400) 
  333. *xend |= ~0x3ff;
  334. *ystart = ks0127_read(ks, KS_VAVB) >> 2;
  335. *yend = ks0127_read(ks, KS_VAVE);
  336. dprintk("ks0127: ystart=%d yend=%dn", *ystart, *yend);
  337. *ystart = (*ystart - 2) * 2;
  338. *yend = (*yend - 2) * 2;
  339. }
  340. static int ks0127_command( struct i2c_device* device, unsigned int cmd, void* arg )
  341. {
  342. struct ks0127* ks = (struct ks0127*)device->data;
  343. int *iarg = (int*)arg;
  344. int size;
  345. int xstart;
  346. int ystart;
  347. int xend;
  348. int yend;
  349. int hav;
  350. int vav;
  351.         if( !ks )
  352.                 return -ENODEV;
  353. dprintk( "ks0127: command %xn", cmd );
  354. switch (cmd)
  355.         {
  356.         case KS0127_RESET:
  357.         dprintk( "ks0127: command KS0127_RESETn" );
  358.                 ks0127_reset( ks );
  359.                 break;
  360.         case KS0127_SET_INPUT:
  361.                 switch( *iarg )
  362.                 {
  363.                 case KS_INPUT_COMPOSITE:
  364.             dprintk( "ks0127: command KS0127_SET_INPUT: INPUT_COMPOSITEn" );
  365.                     ks0127_and_or( ks, KS_CMDA,   0xfc, 0x00 ); /* autodetect 50/60 Hz */
  366.                     ks0127_and_or( ks, KS_CMDB,   0xf0, 0x02 ); /* set input line = AY2 */
  367.                     ks0127_and_or( ks, KS_CMDC,   0x70, 0x0a ); /* non-freerunning mode */
  368.                     ks0127_and_or( ks, KS_CMDD,   0xe7, 0x00 ); /* analog input */
  369.                     ks0127_and_or( ks, KS_CTRACK, 0xc7, 0x00 ); /* enable chroma demodulation */
  370.                     break;
  371.                 case KS_INPUT_SVIDEO:
  372.             dprintk( "ks0127: command KS0127_SET_INPUT: INPUT_SVIDEOn" );
  373.                     ks0127_and_or( ks, KS_CMDA,   0xfc, 0x00 ); /* autodetect 50/60 Hz */
  374.                     ks0127_and_or( ks, KS_CMDB,   0xf0, 0x08 ); /* set input line = AY0-AC0 */
  375.                     ks0127_and_or( ks, KS_CMDC,   0x70, 0x0a ); /* non-freerunning mode */
  376.                     ks0127_and_or( ks, KS_CMDD,   0xe7, 0x00 ); /* analog input */
  377.                     ks0127_and_or( ks, KS_CTRACK, 0xc7, 0x00 ); /* enable chroma demodulation */
  378.                     break;
  379.                 case KS_INPUT_TUNER:
  380.             dprintk( "ks0127: command KS0127_SET_INPUT: INPUT_TUNERn" );
  381.                     ks0127_and_or( ks, KS_CMDA,   0xfc, 0x00 ); /* autodetect 50/60 Hz */
  382.                     ks0127_and_or( ks, KS_CMDB,   0xf0, 0x01 ); /* set input line = AY1 */
  383.                     ks0127_and_or( ks, KS_CMDC,   0x70, 0x0a ); /* non-freerunning mode */
  384.                     ks0127_and_or( ks, KS_CMDD,   0xe7, 0x00 ); /* analog input */
  385.                     ks0127_and_or( ks, KS_CTRACK, 0xc7, 0x00 ); /* enable chroma demodulation */
  386.                     break;
  387.                 case KS_INPUT_YUV656_60HZ:
  388.             dprintk( "ks0127: command KS0127_SET_INPUT: INPUT_YUV656_60HZn" );
  389.                     ks0127_and_or( ks, KS_CMDA,   0xfc, 0x03 ); /* force 60 Hz */
  390.                     ks0127_and_or( ks, KS_CMDB,   0xf0, 0x08 ); /* set input line = AY0-AC0 */
  391.                     ks0127_and_or( ks, KS_CMDC,   0x70, 0x87 ); /* freerunning mode */
  392.                     ks0127_and_or( ks, KS_CMDD,   0xe7, 0x08 ); /* digital input */
  393.                     ks0127_and_or( ks, KS_CTRACK, 0xc7, 0x20 ); /* disable chroma demodulation */
  394.                     break;
  395.                 case KS_INPUT_YUV656_50HZ:
  396.             dprintk( "ks0127: command KS0127_SET_INPUT: INPUT_YUV656_50HZn" );
  397.                     ks0127_and_or( ks, KS_CMDA,   0xfc, 0x02 ); /* force 50 Hz */
  398.                     ks0127_and_or( ks, KS_CMDB,   0xf0, 0x08 ); /* set input line = AY0-AC0 */
  399.                     ks0127_and_or( ks, KS_CMDC,   0x70, 0x87 ); /* freerunning mode */
  400.                     ks0127_and_or( ks, KS_CMDD,   0xe7, 0x08 ); /* digital input */
  401.                     ks0127_and_or( ks, KS_CTRACK, 0xc7, 0x20 ); /* disable chroma demodulation */
  402.                     break;
  403.                 }
  404.                 break;
  405.         case KS0127_SET_OUTPUT:
  406.                 switch( *iarg )
  407.                 {
  408.                 case KS_OUTPUT_YUV656E:
  409.             dprintk( "ks0127: command KS0127_SET_OUTPUT: OUTPUT_YUV656En" );
  410.                     ks0127_and_or( ks, KS_OFMTA, 0xc0, 0x33);
  411.                     break;
  412.                 case KS_OUTPUT_EXV:
  413.             dprintk( "ks0127: command KS0127_SET_OUTPUT: OUTPUT_EXVn" );
  414.                     ks0127_and_or( ks, KS_OFMTA, 0xc0, 0x39 );
  415.                     break;
  416.                 }
  417.                 break;
  418.         case KS0127_SET_STANDARD:
  419.                 /* Set to automatic SECAM/Fsc mode */
  420.                 ks0127_and_or( ks, KS_DEMOD, 0xf0, 0x00 );
  421.                 switch( *iarg )
  422.                 {
  423.                 case KS_STD_NTSC_M:
  424.             dprintk( "ks0127: command KS0127_SET_STANDARD: NTSC_Mn" ); 
  425.                     ks0127_and_or( ks, KS_CHROMA, 0x9f, 0x00 );
  426.     ks->format_height = 240;
  427.     ks->format_width = 704;
  428.                     break;
  429.                 case KS_STD_NTSC_N:
  430.             dprintk( "ks0127: command KS0127_SET_STANDARD: NTSC_Nn" );
  431.                     ks0127_and_or( ks, KS_CHROMA, 0x9f, 0x00 );
  432.     ks->format_height = 240;
  433.     ks->format_width = 704;
  434.                     break;
  435.                 case KS_STD_PAL_N:
  436.             dprintk( "ks0127: command KS0127_SET_STANDARD: PAL_Nn" );
  437.                     ks0127_and_or( ks, KS_CHROMA, 0x9f, 0x60 );
  438.     ks->format_height = 290;
  439.     ks->format_width = 704;
  440.                     break;
  441.                 case KS_STD_PAL_M:
  442.             dprintk( "ks0127: command KS0127_SET_STANDARD: PAL_Mn" );
  443.                     ks0127_and_or( ks, KS_CHROMA, 0x9f, 0x60 );
  444.     ks->format_height = 290;
  445.     ks->format_width = 704;
  446.                     break;
  447.                 case KS_STD_SECAM:
  448.             dprintk( "ks0127: command KS0127_SET_STANDARD: SECAMn" );
  449.     ks->format_height = 290;
  450.     ks->format_width = 704;
  451.                     /* set to secam autodetection */
  452.                     ks0127_and_or( ks, KS_CHROMA, 0xdf, 0x20 );
  453.                     ks0127_and_or( ks, KS_DEMOD, 0xf0, 0x00 );
  454.                     udelay( 100000 );
  455.                     /* did it autodetect? */
  456.                     if( ks0127_read( ks, KS_DEMOD ) & 0x40 )
  457.                         break;
  458.                     /* force to secam mode */
  459.                     ks0127_and_or( ks, KS_DEMOD, 0xf0, 0x0f );
  460.                     break;
  461.                 }
  462.                 break;
  463.         case KS0127_SET_BRIGHTNESS:
  464.                 ks0127_write( ks, KS_BRT, *iarg );
  465.                 break;
  466.         case KS0127_SET_CONTRAST:
  467.                 ks0127_write( ks, KS_CON, *iarg );
  468.                 break;
  469.         case KS0127_SET_HUE:
  470.                 ks0127_write( ks, KS_HUE, *iarg );
  471.                 break;
  472.         case KS0127_SET_SATURATION:
  473.                 ks0127_write( ks, KS_SAT, *iarg );
  474. if (*iarg == 0) 
  475. ks0127_and_or( ks, KS_UVOFFH, 0xb0, 0x00);
  476.  else 
  477. ks0127_and_or( ks, KS_UVOFFL, 0x00, 0x40);
  478.                 break;
  479.         case KS0127_SET_AGC_MODE:
  480.                 switch( *iarg )
  481.                 {
  482.                 case KS_AGC_NORMAL:
  483.                     ks0127_and_or( ks, KS_CMDB, 0x4f, 0x00 );
  484.                     break;
  485.                 case KS_AGC_MODE1:
  486.                     ks0127_and_or( ks, KS_CMDB, 0x4f, 0x80 );
  487.                     break;
  488.                 case KS_AGC_MANUAL:
  489.                     ks0127_and_or( ks, KS_CMDB, 0xcf, 0x10 );
  490.                     break;
  491.                 case KS_AGC_AUTO:
  492.                     ks0127_and_or( ks, KS_CMDB, 0xdf, 0x20 );
  493.                     break;
  494.                 }
  495.                 break;
  496.         case KS0127_SET_AGC:
  497.                 ks0127_write( ks, KS_AGC, *iarg );
  498.                 break;
  499.                 
  500.         case KS0127_SET_CHROMA_MODE:
  501.                 switch( *iarg )
  502.                 {
  503.                 case KS_CHROMA_AUTO:
  504.                     ks0127_and_or( ks, KS_CHROMA, 0xfc, 0x00 );
  505.                     break;
  506.                 case KS_CHROMA_ON:
  507.                     ks0127_and_or( ks, KS_CHROMA, 0xfc, 0x02 );
  508.                     break;
  509.                 case KS_CHROMA_OFF:
  510.                     ks0127_and_or( ks, KS_CHROMA, 0xfc, 0x03 );
  511.                     break;
  512.                 }
  513.                 break;
  514.         case KS0127_SET_PIXCLK_MODE:
  515.                 switch( *iarg )
  516.                 {
  517.                 case KS_PIXCLK_CCIR601:
  518.                     ks0127_and_or( ks, KS_CMDA, 0xfb, 0x04 );
  519.                     break;
  520.                 case KS_PIXCLK_SQUARE:
  521.                     ks0127_and_or( ks, KS_CMDA, 0xfb, 0x00 );
  522.                     break;
  523.                 }
  524.                 break;
  525.         case KS0127_SET_GAMMA_MODE:
  526.                 switch( *iarg )
  527.                 {
  528.                 case KS_GAMMA_OFF:
  529.                     ks0127_and_or( ks, KS_OFMTA, 0x3f, 0x00 );
  530.                     break;
  531.                 case KS_GAMMA_Y:
  532.                     ks0127_and_or( ks, KS_OFMTA, 0x3f, 0x40 );
  533.                     break;
  534.                 
  535.                 case KS_GAMMA_UV:
  536.                     ks0127_and_or( ks, KS_OFMTA, 0x3f, 0x80 );
  537.                     break;
  538.                 case KS_GAMMA_YUV:
  539.                     ks0127_and_or( ks, KS_OFMTA, 0x3f, 0xc0 );
  540.                     break;
  541.                 }
  542.                 break;
  543.         case KS0127_SET_UGAIN:
  544.                 ks0127_write( ks, KS_UGAIN, *iarg );
  545.                 break;
  546.         case KS0127_SET_VGAIN:
  547.                 ks0127_write( ks, KS_VGAIN, *iarg );
  548.                 break;
  549.         case KS0127_SET_INVALY:
  550.                 ks0127_write( ks, KS_INVALY, *iarg );
  551.                 break;
  552.         case KS0127_SET_INVALU:
  553.                 ks0127_write( ks, KS_INVALU, *iarg );
  554.                 break;
  555.         case KS0127_SET_INVALV:
  556.                 ks0127_write( ks, KS_INVALV, *iarg );
  557.                 break;
  558.         case KS0127_SET_UNUSEY:
  559.                 ks0127_write( ks, KS_UNUSEY, *iarg );
  560.                 break;
  561.         case KS0127_SET_UNUSEU:
  562.                 ks0127_write( ks, KS_UNUSEU, *iarg );
  563.                 break;
  564.         case KS0127_SET_UNUSEV:
  565.                 ks0127_write( ks, KS_UNUSEV, *iarg );
  566.                 break;
  567.         case KS0127_SET_VSALIGN_MODE:
  568.                 switch( *iarg )
  569.                 {
  570.                 case KS_VSALIGN0:
  571.                     ks0127_and_or( ks, KS_CMDB, 0xbf, 0x00 );
  572.                     break;
  573.                 case KS_VSALIGN1:
  574.                     ks0127_and_or( ks, KS_CMDB, 0xbf, 0x40 );
  575.                     break;
  576.                 }
  577.                 break;
  578.         case KS0127_SET_OUTPUT_MODE:
  579.                 switch( *iarg )
  580.                 {
  581.                 case KS_OUTPUT_NORMAL:
  582.                     ks0127_and_or( ks, KS_CMDE,  0x7f, 0x00 );
  583.                     ks0127_and_or( ks, KS_OFMTA, 0xcf, 0x00 );
  584.                     break;
  585.                 case KS_OUTPUT_HIZ:
  586.                     ks0127_and_or( ks, KS_CMDE,  0x7f, 0x80 );
  587.                     ks0127_and_or( ks, KS_OFMTA, 0xcf, 0x00 );
  588.                     break;
  589.                 case KS_OUTPUT_SYNC_HIZ:
  590.                     ks0127_and_or( ks, KS_CMDE,  0x7f, 0x80 );
  591.                     ks0127_and_or( ks, KS_OFMTA, 0xcf, 0x10 );
  592.                     break;
  593.                 case KS_OUTPUT_SYNC_CLK_HIZ:
  594.                     ks0127_and_or( ks, KS_CMDE,  0x7f, 0x80 );
  595.                     ks0127_and_or( ks, KS_OFMTA, 0xcf, 0x20 );
  596.                     break;
  597.                 }
  598.                 break;
  599. case KS0127_SET_WIDTH:
  600. ks0127_getcrop( ks, &xstart, &xend, &ystart, &yend);
  601. dprintk("ks0127: xstart=%d xend=%d ystart=%d, yend=%dn",
  602. xstart, xend, ystart, yend);
  603. hav = 720 - (xstart + xend);
  604. vav = yend - ystart;
  605. dprintk("ks0127: hav = %d vav=%dn", hav, vav);
  606. size = (*iarg * 0x7fff) / hav;
  607. ks->cap_width = *iarg;
  608. dprintk("ks0127: width size = %d program = 0x%xn", *iarg, size);
  609. ks0127_and_or( ks, KS_HSCLL, 0x01, size << 1);
  610. ks0127_write( ks, KS_HSCLH, size >> 7);
  611. #ifdef NEVER
  612. /*
  613.  * This little hack can for samsung note was
  614.  * scaler fix -- turn off fifi for at least 1 line
  615.  */
  616. for(i=0; i < 10; i++) 
  617. ks0127_and_or( ks, 0x0d, ~0x03, 0);
  618. ks0127_and_or( ks, 0x0d, ~0x03, 1);
  619. #endif
  620. if (ks->cap_width <= 384) {
  621. ks0127_and_or( ks, KS_VERTIA, ~0x08, 0x00);
  622. } else {
  623. ks0127_and_or( ks, KS_VERTIA, ~0x08, 0x08);
  624. }
  625. break;
  626. case KS0127_SET_HEIGHT:
  627. #ifdef NEVER
  628. ks0127_getcrop( ks, &xstart, &xend, &ystart, &yend);
  629. dprintk("ks0127: xstart=%d xend=%d ystart=%d, yend=%dn",
  630. xstart, xend, ystart, yend);
  631. hav = 720 - (xstart + xend);
  632. vav = yend - ystart;
  633. dprintk("ks0127: hav = %d vav=%dn", hav, vav);
  634. size = (*iarg * 0x3fff) / vav;
  635. ks->cap_height = *iarg;
  636. dprintk("ks0127: height size = %d program = 0x%xn", *iarg, size);
  637. h1 = ks0127_read( ks, KS_HSCLL);
  638. h2 = ks0127_read( ks, KS_HSCLH);
  639. ks0127_and_or( ks, KS_VSCLL, 0x03, 0xfc);
  640. ks0127_write( ks, KS_VSCLH, 0xff);
  641. ks0127_and_or( ks, KS_HSCLL, 0x01, 0xfe);
  642. ks0127_write( ks, KS_HSCLH, 0);
  643. ks0127_and_or( ks, KS_VSCLL, 0x03, size << 2);
  644. ks0127_write( ks, KS_VSCLH, size >> 6);
  645. ks0127_and_or( ks, KS_VERTIB, ~0x06, 0x00);
  646. ks0127_and_or( ks, KS_HSCLL, 0x01, h1);
  647. ks0127_write( ks, KS_HSCLH, h2);
  648. #ifdef NEVER
  649. if (ks->cap_height == ks->format_height) {
  650. ks0127_and_or( ks, KS_VERTIB, ~0x06, 0x04);
  651. } else {
  652. ks0127_and_or( ks, KS_VERTIB, ~0x06, 0x00);
  653. }
  654. if (ks->cap_height <= ks->format_height/2) {
  655. ks0127_and_or( ks, KS_VERTIC, ~0x04, 0x04);
  656. } else {
  657. ks0127_and_or( ks, KS_VERTIC, ~0x04, 0x00);
  658. }
  659. #endif
  660. #endif
  661. break;
  662.         case KS0127_GET_STATUS:
  663.                 *iarg = ks0127_read( ks, KS_STAT );
  664.                 break;
  665. default:
  666. return -EINVAL;
  667. }
  668. return 0;
  669. }
  670. struct i2c_driver i2c_driver_ks0127 = {
  671.         KS0127_DEVNAME,
  672. I2C_DRIVERID_KS0127,
  673. I2C_KS0127_ADDON,
  674.         I2C_KS0127_ONBOARD,
  675. ks0127_attach,
  676. ks0127_detach,
  677. ks0127_command
  678. };
  679. /****************************************************************************
  680. * linux kernel module api
  681. ****************************************************************************/
  682. #ifdef MODULE
  683. int init_module(void)
  684. #else
  685. int ks0127_init(void)
  686. #endif
  687. {
  688. i2c_register_driver( &i2c_driver_ks0127 );
  689. return 0;
  690. }
  691. #ifdef MODULE
  692. void cleanup_module(void)
  693. {
  694. i2c_unregister_driver( &i2c_driver_ks0127 );
  695. }
  696. #endif