auo-tcon-k1900.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. /*
  2. * Disclaimer (blabla)
  3. *
  4. * Author: Manoël Trapier <manoelt@bookeen.com>
  5. * Copyright (c) 2003-2010 Bookeen
  6. *
  7. */
  8. #include <linux/init.h>
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/miscdevice.h>
  12. #include <linux/poll.h>
  13. #include <linux/sched.h>
  14. #include <linux/wait.h>
  15. #include <linux/delay.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/pm.h>
  18. #include <linux/proc_fs.h>
  19. #include <asm/hardware.h>
  20. #include <asm/delay.h>
  21. #include <asm/uaccess.h>
  22. #include <asm-arm/irq.h>
  23. #include <asm/arch/gpio.h>
  24. #include <asm/arch/regs-gpio.h>
  25. #include <asm/arch/regs-irq.h>
  26. #include <asm/arch/regs-lcd.h>
  27. #include <asm-arm/arch-s3c2410/irqs.h>
  28. #include <asm-arm/arch-s3c2410/gpio.h>
  29. #include <linux/irq.h>
  30. #include <linux/platform_device.h>
  31. #include <linux/clk.h>
  32. #include <asm/io.h>
  33. #include <linux/ioctl.h>
  34. #include <linux/auofb_ioctl.h>
  35. #include <cybook.h>
  36. #define DEBUG_MESSAGES
  37. #define DEBUG_TRACEFUNC
  38. #define MODULE_NAME "AUO-TCON"
  39. #define BUSY_WAIT_TIMEOUT (40*5*2) //panel time out = 1s
  40. #define SYS_WR_CON (1<<6)
  41. #define SYS_OE_CON (1<<7)
  42. // ===========================================================================
  43. #undef MSG
  44. #undef DBG
  45. #ifdef DEBUG_MESSAGES
  46. enum InfoLevel
  47. {
  48. INFO_ERROR = 0,
  49. INFO_WARNING,
  50. INFO_NORMAL,
  51. INFO_DEBUG,
  52. INFO_VERBOSE,
  53. };
  54. # ifndef VERBOSE_LEVEL
  55. # define VERBOSE_LEVEL INFO_VERBOSE
  56. # endif
  57. # ifdef DEBUG_TRACEFUNC
  58. static int _dbg_FunctionLevel = 0;
  59. # define MSG(str) {\
  60. int __i;\
  61. printk(KERN_ALERT "+");\
  62. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  63. printk("-");\
  64. printk("||" str "\n");\
  65. }
  66. # define DBG(str, ...) {\
  67. int __i;\
  68. printk(KERN_ALERT "+");\
  69. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  70. printk("-");\
  71. printk("||" str "\n", __VA_ARGS__);\
  72. }
  73. # define INFOL(level, s) do {\
  74. if (level <= VERBOSE_LEVEL) {\
  75. int __i;\
  76. printk(KERN_ALERT "+");\
  77. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  78. printk("-");\
  79. printk("<%d>%s:%s(): ", level, __FILE__, __func__); printk s; printk("\n");\
  80. }\
  81. } while(0)
  82. # define FUNC_IN() {\
  83. int __i;\
  84. _dbg_FunctionLevel++;\
  85. printk(KERN_ALERT "+");\
  86. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  87. printk("-");\
  88. printk(">> %s() >>\n", __func__);\
  89. }
  90. # define FUNC_OUT() {\
  91. int __i;\
  92. printk(KERN_ALERT "+");\
  93. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  94. printk("-");\
  95. printk("<< %s() <<\n", __func__);\
  96. _dbg_FunctionLevel--;\
  97. }
  98. # define FUNC_OUTR(val) {\
  99. int __i;\
  100. printk(KERN_ALERT "+");\
  101. for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
  102. printk("-");\
  103. printk("<< %s() = %d <<\n", __func__, val);\
  104. _dbg_FunctionLevel--;\
  105. }
  106. # else /* DEBUG_TRACEFUNC */
  107. # define MSG(str) do {\
  108. printk(KERN_ALERT MODULE_NAME ": " str "\n");\
  109. } while(0)
  110. # define DBG(str, ...) do {\
  111. printk(KERN_ALERT MODULE_NAME ": " str "\n", __VA_ARGS__);\
  112. } while(0)
  113. # define FUNC_IN() do {\
  114. } while(0)
  115. # define FUNC_OUT() do {\
  116. } while(0)
  117. # define FUNC_OUTR(val) do {\
  118. printk(KERN_ALERT MODULE_NAME ": %s() return %d\n", __func__, val);\
  119. } while(0)
  120. #define INFOL(level, s) do {\
  121. if (level <= VERBOSE_LEVEL) {\
  122. printk("<%d>%s:%s(): ", level, __FILE__, __func__); printk s; printk("\n");\
  123. }\
  124. } while(0)
  125. # endif /* DEBUG_TRACEFUNC */
  126. #else /* DEBUG_MESSAGES */
  127. # define MSG(str)
  128. # define DBG(str, ...)
  129. # define FUNC_IN()
  130. # define FUNC_OUT()
  131. # define FUNC_OUTR(val)
  132. # define INFOL(level, s)
  133. # define INFO(s)
  134. #endif /* DEBUG_MESSAGES */
  135. // ===========================================================================
  136. #define VIDCON0_S_CPU_IF_MAIN (2<<22)
  137. #define VIDCON0_S_RGB_PAR (0<<13)
  138. #define VIDCON0_S_VCLK_GATING_OFF (1<<5)
  139. #define VIDCON0_S_CLKDIR_DIVIDED (1<<4)
  140. #define VIDCON0_S_CLKSEL_HCLK (0<<2)
  141. #define VIDCON0_CLKVAL_F_SHIFT (6)
  142. #define VIDTCON2_LINEVAL_S (11)
  143. static int tcon_inPortraitMode = 0;
  144. typedef enum Tcon_Speedclasses
  145. {
  146. EN_I80_NONE = -1,
  147. EN_I80_LANDSCAPE = 0,
  148. EN_I80_PORTRAIT,
  149. EN_I80_LANDSCAPE_HANDWRITING,
  150. EN_I80_PORTRAIT_HANDWRITING,
  151. } Tcon_Speedclasses;
  152. typedef struct Tcon_SpeedclasseValue
  153. {
  154. u8 cs_setup;
  155. u8 wr_setup;
  156. u8 wr_act;
  157. u8 wr_hold;
  158. } Tcon_SpeedclasseValue;
  159. static Tcon_SpeedclasseValue tcon_speedtable[] =
  160. {
  161. [EN_I80_LANDSCAPE] =
  162. {
  163. .cs_setup = 0,
  164. .wr_setup = 0,
  165. .wr_act = 1,
  166. .wr_hold = 0,
  167. },
  168. [EN_I80_PORTRAIT] =
  169. {
  170. .cs_setup = 0,
  171. .wr_setup = 3,
  172. .wr_act = 8,
  173. .wr_hold = 3,
  174. },
  175. [EN_I80_LANDSCAPE_HANDWRITING] =
  176. {
  177. .cs_setup = 0,
  178. .wr_setup = 1,
  179. .wr_act = 1,
  180. .wr_hold = 0,
  181. },
  182. [EN_I80_PORTRAIT_HANDWRITING] =
  183. {
  184. .cs_setup = 0,
  185. .wr_setup = 2,
  186. .wr_act = 6,
  187. .wr_hold = 2,
  188. },
  189. };
  190. static Tcon_Speedclasses tcon_currentSpeedClass = EN_I80_NONE;
  191. // ===========================================================================
  192. // TCON Related functions
  193. // ===========================================================================
  194. /*
  195. 1. loops = 1 --> 25ns
  196. 2. loops = 75 --> 1 us
  197. 3. loops = 100000 --> 1ms
  198. */
  199. static inline void tcon_ndelay(unsigned long loops) //in ns
  200. {
  201. __asm__ volatile ("1:\n" "subs %0, %1, #1\n" "bne 1b":"=r" (loops):"0"(loops));
  202. }
  203. static inline void tcon_delay (unsigned long uTime)
  204. {
  205. unsigned long cnt = 0;
  206. for ( cnt = 0; cnt < uTime; cnt++ )
  207. tcon_ndelay(75);
  208. }
  209. static int tcon_wait_ready (void)
  210. {
  211. unsigned long tmp;
  212. int iBusyCnt = 0;
  213. wait_queue_head_t busy_wq;
  214. init_waitqueue_head(&busy_wq);
  215. tmp = __raw_readl(S3C2410_GPBDAT);
  216. while ( (tmp & (1 << 2)) == 0 )
  217. {
  218. sleep_on_timeout(&busy_wq, 4);
  219. iBusyCnt++;
  220. if ( iBusyCnt >= BUSY_WAIT_TIMEOUT )
  221. {
  222. return 0;
  223. }
  224. tmp = __raw_readl(S3C2410_GPBDAT);
  225. }
  226. return 1;
  227. }
  228. /* On the i80 port,
  229. * i80 TCON
  230. * -----------
  231. * RS -> D/C
  232. * CS0 -> CSEL
  233. * nWE -> HWE
  234. * OE -> HRD
  235. */
  236. static inline void tcon_i80bus_init_interface(void)
  237. {
  238. unsigned long tmp;
  239. FUNC_IN();
  240. tmp = __raw_readl(S3C_SYSIFCON0); //polarity of RS, set 1 for normal access
  241. tmp |= (1<<2);
  242. __raw_writel(tmp, S3C_SYSIFCON0);
  243. tmp = __raw_readl(S3C_SIFCCON0); // command mode enable
  244. tmp |= (1<<0);
  245. __raw_writel(tmp, S3C_SIFCCON0);
  246. FUNC_OUT();
  247. }
  248. static inline void tcon_i80bus_deinit_interface(void)
  249. {
  250. unsigned long tmp;
  251. FUNC_IN();
  252. tmp = __raw_readl(S3C_SIFCCON0); // command mode disable
  253. tmp &= ~(1<<0);
  254. __raw_writel(tmp, S3C_SIFCCON0);
  255. FUNC_OUT();
  256. }
  257. void tcon_i80bus_set_speed(Tcon_Speedclasses i80_speed,
  258. unsigned short display_w,
  259. unsigned short display_h,
  260. unsigned char set_clock)
  261. {
  262. unsigned long tmp;
  263. unsigned char clkval = 0;
  264. unsigned short h_cnt, v_cnt;
  265. unsigned long vclk;
  266. struct clk *lcd_clock;
  267. int HCLK;
  268. FUNC_IN();
  269. if ( tcon_currentSpeedClass == EN_I80_NONE)
  270. set_clock = true;
  271. tcon_currentSpeedClass = i80_speed;
  272. if (set_clock == true)
  273. {
  274. INFOL(INFO_VERBOSE, ("Will set clocks..."));
  275. tmp = __raw_readl(S3C_VIDCON0);
  276. tmp = VIDCON0_S_CPU_IF_MAIN | VIDCON0_S_RGB_PAR | \
  277. VIDCON0_S_VCLK_GATING_OFF | \
  278. VIDCON0_S_CLKDIR_DIVIDED | VIDCON0_S_CLKSEL_HCLK;
  279. __raw_writel(tmp, S3C_VIDCON0);
  280. v_cnt = display_h;
  281. h_cnt = display_w;
  282. lcd_clock = clk_get(NULL, "hclk");
  283. HCLK = clk_get_rate(lcd_clock);
  284. clkval = (unsigned int)(HCLK / (display_w * display_h * 50 /* FPS ???? */));
  285. vclk = (HCLK / (clkval + 1)) / 1000;
  286. tmp = __raw_readl(S3C_VIDCON0);
  287. tmp |= (clkval << VIDCON0_CLKVAL_F_SHIFT);
  288. __raw_writel(tmp, S3C_VIDCON0);
  289. }
  290. tmp = __raw_readl(S3C_SYSIFCON0);
  291. tmp = (tcon_speedtable[i80_speed].cs_setup << 16) |
  292. (tcon_speedtable[i80_speed].wr_setup << 12) |
  293. (tcon_speedtable[i80_speed].wr_act << 8) |
  294. (tcon_speedtable[i80_speed].wr_hold << 4) |
  295. (1 << 2) | (1 << 1) | (1);
  296. __raw_writel(tmp, S3C_SYSIFCON0);
  297. tmp = __raw_readl(S3C_SYSIFCON1);
  298. tmp = (tcon_speedtable[i80_speed].cs_setup << 16) |
  299. (tcon_speedtable[i80_speed].wr_setup << 12) |
  300. (tcon_speedtable[i80_speed].wr_act << 8) |
  301. (tcon_speedtable[i80_speed].wr_hold << 4) |
  302. (1 << 2) | (1 << 1) | (1);
  303. __raw_writel(tmp, S3C_SYSIFCON1);
  304. tmp = __raw_readl(S3C_VIDTCON2);
  305. tmp = ((display_h - 1) << VIDTCON2_LINEVAL_S) | ((display_w / 4) - 1);
  306. __raw_writel(tmp, S3C_VIDTCON2);
  307. FUNC_OUT();
  308. }
  309. static inline void tcon_i80bus_write (int data)
  310. {
  311. int tmp;
  312. tmp = __raw_readl(S3C_SIFCCON0); // nWE enable
  313. tmp |= SYS_WR_CON;
  314. __raw_writel(tmp, S3C_SIFCCON0);
  315. if ( !tcon_inPortraitMode )
  316. tcon_ndelay(25);
  317. __raw_writel(data, S3C_SIFCCON1); //rSIFCCON1 = CMD;
  318. tmp = __raw_readl(S3C_SIFCCON0); // nWE disables
  319. tmp &= ~SYS_WR_CON;
  320. __raw_writel(tmp, S3C_SIFCCON0);
  321. }
  322. static inline void tcon_set_write_to_data(void)
  323. {
  324. unsigned long tmp;
  325. //FUNC_IN();
  326. tmp = __raw_readl(S3C_SIFCCON0);
  327. // RS high -> D/nC set Data mode
  328. tmp |= (1<<1);
  329. __raw_writel(tmp, S3C_SIFCCON0);
  330. tcon_delay(1);
  331. //FUNC_OUT();
  332. }
  333. static inline void tcon_set_write_to_command(void)
  334. {
  335. unsigned long tmp;
  336. //FUNC_IN();
  337. tmp = __raw_readl(S3C_SIFCCON0);
  338. // RS low -> D/nC set Command mode
  339. tmp &= ~(1<<1);
  340. __raw_writel(tmp, S3C_SIFCCON0);
  341. tcon_delay(1);
  342. //FUNC_OUT();
  343. }
  344. static inline void tcon_enable_write(void)
  345. {
  346. unsigned long tmp;
  347. FUNC_IN();
  348. tmp = __raw_readl(S3C_SIFCCON0);
  349. // nWE -> HWE enable
  350. tmp |= (1<<6);
  351. __raw_writel(tmp, S3C_SIFCCON0);
  352. tcon_delay(1);
  353. FUNC_OUT();
  354. }
  355. static inline void tcon_disable_write(void)
  356. {
  357. unsigned long tmp;
  358. FUNC_IN();
  359. tmp = __raw_readl(S3C_SIFCCON0);
  360. // nWE -> HWE disable
  361. tmp &= ~(1<<6);
  362. __raw_writel(tmp, S3C_SIFCCON0);
  363. tcon_delay(1);
  364. FUNC_OUT();
  365. }
  366. static inline void tcon_enable_read(void)
  367. {
  368. unsigned long tmp;
  369. FUNC_IN();
  370. tmp = __raw_readl(S3C_SIFCCON0); // nRD enable
  371. tmp |= SYS_OE_CON;
  372. __raw_writel(tmp, S3C_SIFCCON0);
  373. tcon_delay(1);
  374. FUNC_OUT();
  375. }
  376. static inline void tcon_disable_read(void)
  377. {
  378. unsigned long tmp;
  379. FUNC_IN();
  380. tmp = __raw_readl(S3C_SIFCCON0); // nRD disable
  381. tmp &= ~SYS_OE_CON;
  382. __raw_writel(tmp, S3C_SIFCCON0);
  383. tcon_delay(1);
  384. FUNC_OUT();
  385. }
  386. static inline void tcon_select_chip(void)
  387. {
  388. unsigned long tmp;
  389. FUNC_IN();
  390. tmp = __raw_readl(S3C_SIFCCON0); // Chip Select
  391. tmp |= (1<<8);
  392. __raw_writel(tmp, S3C_SIFCCON0);
  393. tcon_delay(1);
  394. FUNC_OUT();
  395. }
  396. static inline void tcon_unselect_chip(void)
  397. {
  398. unsigned long tmp;
  399. FUNC_IN();
  400. tmp = __raw_readl(S3C_SIFCCON0); // nCS0(Main) enable
  401. tmp &= ~(1<<8);
  402. __raw_writel(tmp, S3C_SIFCCON0);
  403. tcon_delay(1);
  404. FUNC_OUT();
  405. }
  406. int tcon_send_command_start(sAUOCommand *cmd)
  407. {
  408. FUNC_IN();
  409. INFOL(INFO_VERBOSE,("cmd #%08lX", cmd->cmd));
  410. /* First: verify that the K1900 is ready */
  411. INFOL(INFO_VERBOSE, ("/* First: verify that the K1900 is ready */"));
  412. if (GET_COMMAND_NEED_WAIT(cmd->cmd) != 0x00)
  413. {
  414. INFOL(INFO_VERBOSE, ("Wait for non BUSY..."));
  415. tcon_wait_ready();
  416. }
  417. if (cmd->cmd == AUOCMD_INIT_SET)
  418. {
  419. tcon_inPortraitMode = ~(cmd->params[0]) & (0x1 << 10);
  420. if (tcon_inPortraitMode)
  421. tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false);
  422. else
  423. tcon_i80bus_set_speed(EN_I80_LANDSCAPE, 600, 800, false);
  424. INFOL(INFO_VERBOSE, ("Rotation set to 0x%08X...", tcon_inPortraitMode));
  425. }
  426. /* Second: init the i80 interface */
  427. INFOL(INFO_VERBOSE, ("/* Second: init the i80 interface */"));
  428. tcon_i80bus_init_interface();
  429. /* Third: Select the chip and set to Command mode */
  430. INFOL(INFO_VERBOSE, ("/* Third: Select the chip and set to Command mode */"));
  431. tcon_select_chip();
  432. tcon_set_write_to_command();
  433. /* Fourth: Send command */
  434. INFOL(INFO_VERBOSE, ("/* Fourth: Send command */"));
  435. tcon_i80bus_write(cmd->cmd & 0xFFFF); /* This function already manage
  436. * no need to do it here. */
  437. /* Sixth: If parameters is needed, send them */
  438. INFOL(INFO_VERBOSE, ("/* Sixth: If parameters is needed, send them */"));
  439. if (GET_COMMAND_PARAM_NUM(cmd->cmd) > 0)
  440. {
  441. int i, paramNumbers = GET_COMMAND_PARAM_NUM(cmd->cmd);
  442. INFOL(INFO_VERBOSE, ("YES! We have %d parameters", paramNumbers));
  443. tcon_set_write_to_data();
  444. for (i = 0; i < paramNumbers; i++)
  445. {
  446. INFOL(INFO_VERBOSE, (" parameter [%02d] = 0x%04X", i, cmd->params[i]));
  447. tcon_i80bus_write(cmd->params[i]);
  448. }
  449. }
  450. FUNC_OUT();
  451. return 0;
  452. }
  453. int tcon_send_data(unsigned short *buffer, unsigned long bufferLen)
  454. {
  455. /* Seventh: Send data if needed */
  456. unsigned long i;
  457. //FUNC_IN();
  458. //INFOL(INFO_VERBOSE, ("Bufferlen: %ld", bufferLen));
  459. tcon_set_write_to_data();
  460. for (i = 0; i < bufferLen; i++)
  461. {
  462. tcon_i80bus_write(buffer[i]);
  463. }
  464. //FUNC_OUT();
  465. return 0;
  466. }
  467. int tcon_send_command_end(sAUOCommand *cmd)
  468. {
  469. FUNC_IN();
  470. INFOL(INFO_VERBOSE,("cmd #%08lX START:[#%08X]", cmd->cmd, AUOCMD_DISPLAY_START));
  471. if (cmd->cmd == AUOCMD_DISPLAY_START)
  472. {
  473. tcon_set_write_to_command();
  474. INFOL(INFO_VERBOSE, ("/* Eight: Send STOP command */"));
  475. tcon_i80bus_write(AUOCMD_DISPLAY_STOP & 0xFFFF);
  476. tcon_set_write_to_data();
  477. }
  478. INFOL(INFO_VERBOSE, ("/* Nineth: Close all */"));
  479. tcon_unselect_chip();
  480. tcon_i80bus_deinit_interface();
  481. FUNC_OUT();
  482. return 0;
  483. }
  484. // ===========================================================================
  485. // Device related functions
  486. // ===========================================================================
  487. static int tcon_open (struct inode *inode, struct file *file)
  488. {
  489. FUNC_IN();
  490. FUNC_OUT();
  491. return 0;
  492. }
  493. // ---------------------------------------------------------------------------
  494. static int tcon_release (struct inode *inode, struct file *file)
  495. {
  496. FUNC_IN();
  497. FUNC_OUT();
  498. return 0;
  499. }
  500. // ---------------------------------------------------------------------------
  501. ssize_t tcon_read (struct file *file, char *buf, size_t count, loff_t *ppos)
  502. {
  503. FUNC_IN();
  504. FUNC_OUT();
  505. return 0;
  506. }
  507. // ---------------------------------------------------------------------------
  508. int tcon_ioctl (struct inode *inode, struct file *file,
  509. unsigned int ioctl_cmd, unsigned long arg)
  510. {
  511. sAUOCommand cmd;
  512. unsigned char buffer[2048];
  513. unsigned char *user_buffer;
  514. unsigned long user_buflen, copysize, copysize16;
  515. unsigned short *ptr16;
  516. void __user *argp = (void __user *)arg;
  517. FUNC_IN();
  518. switch ( ioctl_cmd )
  519. {
  520. /* [MTR] */
  521. case IOCTL_AUO_SENDCOMMAND:
  522. if ( copy_from_user(&cmd, argp, sizeof (cmd)) )
  523. return -EFAULT;
  524. /* Now execute the command */
  525. tcon_send_command_start(&cmd);
  526. ///INFOL(INFO_VERBOSE, ("/* Seventh: Send data if needed */"));
  527. if ( GET_COMMAND_HAVE_DATA(cmd.cmd) != 0 )
  528. {
  529. //INFOL(INFO_VERBOSE, ("Yes, we have data to send!"));
  530. user_buflen = cmd.datalen;
  531. user_buffer = (unsigned char *)cmd.data;
  532. while ( user_buflen != 0 )
  533. {
  534. copysize = user_buflen;
  535. if ( user_buflen > sizeof (buffer) )
  536. copysize = sizeof (buffer);
  537. if ( copy_from_user(buffer, user_buffer, copysize) )
  538. return -EFAULT;
  539. copysize16 = (copysize + 1) / 2;
  540. //printk(KERN_ERR "cp16=%ld cp=%ld\n", copysize16, copysize);
  541. ptr16 = (unsigned short *)buffer;
  542. tcon_send_data((unsigned short *)buffer, copysize16);
  543. user_buflen -= copysize;
  544. user_buffer += copysize;
  545. }
  546. }
  547. tcon_send_command_end(&cmd);
  548. break;
  549. }
  550. FUNC_OUT();
  551. return -EINVAL;
  552. }
  553. // ===========================================================================
  554. static struct file_operations s_tcon_fops =
  555. {
  556. owner : THIS_MODULE,
  557. read : tcon_read,
  558. ioctl : tcon_ioctl,
  559. open : tcon_open,
  560. release : tcon_release,
  561. };
  562. static struct miscdevice s_tcon_dev =
  563. {
  564. .minor = 242,
  565. .name = "epaper",
  566. .fops = &s_tcon_fops,
  567. };
  568. // ===========================================================================
  569. // ---------------------------------------------------------------------------
  570. static int tcon_probe (struct platform_device *dev)
  571. {
  572. int ret = -EINVAL;
  573. FUNC_IN();
  574. printk("tcon: probe");
  575. if ( GET_CAPABILITY(PLAT_CAP_VTCON) )
  576. {
  577. unsigned long tmp;
  578. printk(" ok\n");
  579. ret = 0;
  580. // set gpio for lcd
  581. tmp = __raw_readl(S3C2410_GPCCON);
  582. //tmp = (tmp & ~(0xffff03ff))|(0xaaaa02aa);
  583. tmp = (tmp & ~(0xffff033f)) | (0xaaaa022a); //Do not config SYS_CS1(GPC3)
  584. __raw_writel(tmp, S3C2410_GPCCON);
  585. printk("Cybook Orizon Layout\n");
  586. tmp = __raw_readl(S3C2410_GPDCON); //tmp=0x40000
  587. tmp = (tmp & ~(0x0CFFFF)) | (0x04AAAA);
  588. __raw_writel(tmp, S3C2410_GPDCON); // GPD9 is RST_N
  589. __raw_writel(0, S3C2410_GPCUP); //S3C2410_GPCUP = 0;
  590. __raw_writel(0, S3C2410_GPDUP); //S3C2410_GPDUP = 0;
  591. tcon_i80bus_set_speed(EN_I80_LANDSCAPE, 800, 600, true);
  592. // POWER pin config
  593. tmp = __raw_readl(S3C2410_GPBCON);
  594. tmp = (tmp & ~(3 << 6)) | (1 << 6);
  595. __raw_writel(tmp, S3C2410_GPBCON);
  596. // BUSY pin config
  597. tmp = __raw_readl(S3C2410_GPBCON);
  598. tmp = (tmp & ~(3 << 4));
  599. __raw_writel(tmp, S3C2410_GPBCON);
  600. // SLEEP pin config
  601. tmp = __raw_readl(S3C2410_GPBCON);
  602. tmp = (tmp & ~(3 << 2)) | (1 << 2);
  603. __raw_writel(tmp, S3C2410_GPBCON);
  604. msleep(1);
  605. // Panel power on
  606. tmp = __raw_readl(S3C2410_GPBDAT);
  607. tmp |= (1 << 3);
  608. //SLP_N high
  609. tmp |= (1 << 1);
  610. __raw_writel(tmp, S3C2410_GPBDAT);
  611. msleep(100);
  612. // LCD module reset
  613. tmp = __raw_readl(S3C2410_GPDDAT);
  614. tmp |= (1 << 9);
  615. __raw_writel(tmp, S3C2410_GPDDAT);
  616. tmp = __raw_readl(S3C2410_GPDDAT); // goes to LOW
  617. tmp &= ~(1 << 9);
  618. __raw_writel(tmp, S3C2410_GPDDAT);
  619. tcon_delay(5);
  620. tmp = __raw_readl(S3C2410_GPDDAT); // goes to HIGH
  621. tmp |= (1 << 9);
  622. __raw_writel(tmp, S3C2410_GPDDAT);
  623. // delay about 10ms
  624. msleep(10);
  625. tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false);
  626. }
  627. else
  628. printk(" not ok\n");
  629. FUNC_OUTR(ret);
  630. return ret;
  631. }
  632. // ---------------------------------------------------------------------------
  633. static int tcon_remove (struct platform_device *dev)
  634. {
  635. FUNC_IN();
  636. misc_deregister(&s_tcon_dev);
  637. FUNC_OUT();
  638. return 0;
  639. }
  640. // --------------------------------------------------------------------------
  641. static int tcon_resume (struct platform_device *dev)
  642. {
  643. FUNC_IN();
  644. FUNC_OUT();
  645. return 0;
  646. }
  647. // --------------------------------------------------------------------------
  648. static int tcon_suspend (struct platform_device *dev, pm_message_t state)
  649. {
  650. FUNC_IN();
  651. DBG("state event: %X", state.event);
  652. FUNC_OUT();
  653. return 0;
  654. }
  655. // ---------------------------------------------------------------------------
  656. static struct platform_driver tcon_driver ={
  657. .driver =
  658. {
  659. .name = "epaper-tcon",
  660. .owner = THIS_MODULE,
  661. },
  662. .probe = tcon_probe,
  663. .remove = tcon_remove,
  664. .suspend = tcon_suspend,
  665. .resume = tcon_resume,
  666. };
  667. // ---------------------------------------------------------------------------
  668. // ===========================================================================
  669. static int __init tcon_init (void)
  670. {
  671. int ret = 0;
  672. FUNC_IN();
  673. printk("tcon: init\n");
  674. if ( misc_register(&s_tcon_dev) )
  675. {
  676. ret = -EBUSY;
  677. goto exit;
  678. }
  679. platform_driver_register(&tcon_driver);
  680. exit:
  681. FUNC_OUTR(ret);
  682. return ret;
  683. }
  684. // ---------------------------------------------------------------------------
  685. static void __exit tcon_exit (void)
  686. {
  687. FUNC_IN();
  688. printk("tcon: exit\n");
  689. platform_driver_unregister(&tcon_driver);
  690. misc_deregister(&s_tcon_dev);
  691. FUNC_OUT();
  692. }
  693. // ---------------------------------------------------------------------------
  694. module_init (tcon_init);
  695. module_exit (tcon_exit);
  696. // ---------------------------------------------------------------------------
  697. MODULE_LICENSE ("GPL");
  698. MODULE_AUTHOR ("Bookeen <developers@bookeen.com>");
  699. MODULE_DESCRIPTION ("AUO ePaper TCON Driver");
  700. MODULE_VERSION ("1.0");
  701. // ==========================================================================