RX_498HX_615B_82.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2015. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. *
  31. * The following software/firmware and/or related documentation ("MediaTek Software")
  32. * have been modified by MediaTek Inc. All revisions are subject to any receiver\'s
  33. * applicable license agreements with MediaTek Inc.
  34. */
  35. #ifndef BUILD_LK
  36. #include <linux/string.h>
  37. #else
  38. #include <string.h>
  39. #endif
  40. #include "lcm_drv.h"
  41. #ifdef BUILD_LK
  42. #include <platform/mt_gpio.h>
  43. #include <platform/mt_pmic.h>
  44. #elif defined(BUILD_UBOOT)
  45. #include <asm/arch/mt_gpio.h>
  46. #else
  47. #include <mach/mt_gpio.h>
  48. #include <mach/mt_pm_ldo.h>
  49. #endif
  50. #if defined(BUILD_LK)
  51. #define LCM_DEBUG(fmt,arg...) printf("[Eric][lk]""[%s]"fmt"\n",__func__,##arg)
  52. #elif defined(BUILD_UBOOT)
  53. #define LCM_DEBUG(fmt,arg...) printf("[Eric][uboot]""[%s]"fmt"\n",__func__,##arg)
  54. #else
  55. #define LCM_DEBUG(fmt,arg...) printk("[Eric][kernel]""[%s]"fmt"\n",__func__,##arg)
  56. #endif
  57. // ---------------------------------------------------------------------------
  58. // Local Constants
  59. // ---------------------------------------------------------------------------
  60. #define FRAME_WIDTH (480)
  61. #define FRAME_HEIGHT (854)
  62. // ---------------------------------------------------------------------------
  63. // Data ID
  64. // ---------------------------------------------------------------------------
  65. #define DSI_DCS_SHORT_PACKET_ID_0 0x05
  66. #define DSI_DCS_SHORT_PACKET_ID_1 0x15
  67. #define DSI_DCS_LONG_PACKET_ID 0x39
  68. // ---------------------------------------------------------------------------
  69. // Local Variables
  70. // ---------------------------------------------------------------------------
  71. static LCM_UTIL_FUNCS lcm_util = {0};
  72. #define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v)))
  73. #define UDELAY(n) (lcm_util.udelay(n))
  74. #define MDELAY(n) (lcm_util.mdelay(n))
  75. #define REGFLAG_DELAY 0XFE
  76. #define REGFLAG_END_OF_TABLE 0x100 // END OF REGISTERS MARKER
  77. // ---------------------------------------------------------------------------
  78. // Local Functions
  79. // ---------------------------------------------------------------------------
  80. #define dsi_set_cmdq_V3(para_tbl, size, force_update) lcm_util.dsi_set_cmdq_V3(para_tbl, size, force_update)
  81. #define dsi_set_cmdq_V2(cmd, count, ppara, force_update) lcm_util.dsi_set_cmdq_V2(cmd, count, ppara, force_update)
  82. #define dsi_set_cmdq(pdata, queue_size, force_update) lcm_util.dsi_set_cmdq(pdata, queue_size, force_update)
  83. #define wrtie_cmd(cmd) lcm_util.dsi_write_cmd(cmd)
  84. #define write_regs(addr, pdata, byte_nums) lcm_util.dsi_write_regs(addr, pdata, byte_nums)
  85. //#define read_reg(cmd) lcm_util.DSI_dcs_read_lcm_reg(cmd)
  86. #define read_reg_v2(cmd, buffer, buffer_size) lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size)
  87. #define AGOLD_CMD_MODE 0
  88. #if (AGOLD_CMD_MODE)
  89. #define LCM_DSI_CMD_MODE 1
  90. #endif
  91. struct LCM_setting_table {
  92. unsigned cmd;
  93. unsigned char count;
  94. unsigned char para_list[64];
  95. };
  96. static struct LCM_setting_table lcm_initialization_setting[] = {
  97. #if 0
  98. // SET password
  99. {0xB9, 3, {0xFF,0x83,0x79}},
  100. {0xBA, 1, {0x51}},
  101. // Issue DSC NOP command
  102. {0xB1, 19, {0x00,0x50,0x44,0xEA,0x8D,0x08,0x11,0x11,0x11,0x27,
  103. 0x2F,0x9A,0x1A,0x42,0x0B,0x6E,0xF1,0x00,0xE6}},
  104. {0xB2, 13, {0x00,0x00,0xFE,0x08,0x04,0x19,0x22,0x00,0xFF,0x08,
  105. 0x04,0x19,0x20}},
  106. {0xB4, 31, {0x80,0x08,0x00,0x32,0x10,0x03,0x32,0x13,0x70,0x32,
  107. 0x10,0x08,0x37,0x01,0x28,0x07,0x37,0x08,0x4C,0x20,
  108. 0x44,0x44,0x08,0x00,0x40,0x08,0x28,0x08,0x30,0x30,
  109. 0x04}},
  110. {0xD5, 47, {0x00,0x00,0x0A,0x00,0x01,0x05,0x00,0x03,0x00,0x88,
  111. 0x88,0x88,0x88,0x23,0x01,0x67,0x45,0x02,0x13,0x88,
  112. 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x54,
  113. 0x76,0x10,0x32,0x31,0x20,0x88,0x88,0x88,0x88,0x88,
  114. 0x88,0x00,0x00,0x00,0x00,0x00,0x00}},
  115. {0xE0, 35, {0x79,0x00,0x01,0x02,0x22,0x23,0x30,0x23,0x43,0x00,
  116. 0x01,0x12,0x17,0x19,0x17,0x17,0x13,0x18,0x00,0x01,
  117. 0x02,0x22,0x23,0x30,0x23,0x43,0x00,0x01,0x12,0x17,
  118. 0x19,0x17,0x17,0x13,0x18}},
  119. {0xCC, 1, {0x02}},
  120. {0xB6, 4, {0x00,0x88,0x00,0x88}},
  121. // Sleep Out
  122. {0x11, 1, {0X00}},
  123. {REGFLAG_DELAY, 150, {}},
  124. // Display On
  125. {0x29, 1, {0X00}},
  126. {REGFLAG_DELAY, 50, {}},
  127. #else
  128. {0xB9,3,{ 0xFF ,0x83 ,0x79}},
  129. {0xBA,1,{ 0x51}},
  130. {0xB1,19,{ 0x00 ,0x50 ,0x44 ,0xEA ,0x8D ,0x08 ,0x11 ,0x11 ,0x11 ,0x25 ,0x2d ,0x9A ,0x1A ,0x42 ,0x0B ,0x66 ,0xF1 ,0x00 ,0xE6}},
  131. {0xB2,13,{ 0x00 ,0x00 ,0xFE ,0x08 ,0x04 ,0x19 ,0x12 ,0x00 ,0xFF ,0x08 ,0x04 ,0x19 ,0x20}},
  132. {0xB4,31,{ 0x80 ,0x08 ,0x00 ,0x32 ,0x10 ,0x03 ,0x32 ,0x13 ,0x70 ,0x32 ,0x10 ,0x08 ,0x37 ,0x01 ,0x28 ,0x07 ,0x37 ,0x08 ,0x3C ,0x20 ,0x44 ,0x44 ,0x08 ,0x00 ,0x40 ,0x08 ,0x28 ,0x08 ,0x30 ,0x30 ,0x08}},
  133. {0xD5,47,{ 0x00 ,0x00 ,0x0a ,0x00 ,0x01 ,0x05 ,0x00 ,0x03 ,0x00 ,0x88 ,0x88 ,0x88 ,0x88 ,0x23 ,0x01 ,0x67 ,0x45 ,0x02 ,0x13 ,0x88 ,0x88 ,0x88 ,0x88 ,0x88 ,0x88 ,0x88 ,0x88 ,0x88 ,0x88 ,0x54 ,0x76 ,0x10 ,0x32 ,0x31 ,0x20 ,0x88 ,0x88 ,0x88 ,0x88 ,0x88 ,0x88 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00}},
  134. {0xE0,35,{ 0x79 ,0x05 ,0x0F ,0x14 ,0x26 ,0x29 ,0x3F ,0x2B ,0x45 ,0x04 ,0x0E ,0x13 ,0x17 ,0x18 ,0x16 ,0x16 ,0x12 ,0x17 ,0x05 ,0x0F ,0x14 ,0x26 ,0x29 ,0x3F ,0x2B ,0x45 ,0x04 ,0x0E ,0x13 ,0x17 ,0x18 ,0x16 ,0x16 ,0x12 ,0x17}},
  135. {0xCC,1,{ 0x02}},
  136. {0xB6,4,{ 0x00 ,0x88 ,0x00 ,0x88}}, //83
  137. {0x36,1,{ 0x00}},
  138. {0x3A,1,{ 0x77}},
  139. {0x11,0,{}},
  140. {REGFLAG_DELAY, 150, {}},
  141. {0x29,0,{}},
  142. {REGFLAG_DELAY, 20, {}},
  143. #endif
  144. };
  145. #if 0
  146. static struct LCM_setting_table lcm_set_window[] = {
  147. {0x2A, 4, {0x00, 0x00, (FRAME_WIDTH>>8), (FRAME_WIDTH&0xFF)}},
  148. {0x2B, 4, {0x00, 0x00, (FRAME_HEIGHT>>8), (FRAME_HEIGHT&0xFF)}},
  149. {REGFLAG_END_OF_TABLE, 0x00, {}}
  150. };
  151. static struct LCM_setting_table lcm_sleep_out_setting[] = {
  152. // Sleep Out
  153. {0x11, 0, {0x00}},
  154. {REGFLAG_DELAY, 120, {}},
  155. // Display ON
  156. {0x29, 0, {0x00}},
  157. {REGFLAG_DELAY, 10, {}},
  158. {REGFLAG_END_OF_TABLE, 0x00, {}}
  159. };
  160. static struct LCM_setting_table lcm_deep_sleep_mode_in_setting[] = {
  161. // Display off sequence
  162. {0x28, 0, {0x00}},
  163. // Sleep Mode On
  164. {0x10, 0, {0x00}},
  165. {REGFLAG_END_OF_TABLE, 0x00, {}}
  166. };
  167. #endif
  168. static struct LCM_setting_table lcm_backlight_level_setting[] = {
  169. {0x51, 1, {0xFF}},
  170. {REGFLAG_END_OF_TABLE, 0x00, {}}
  171. };
  172. static void push_table(struct LCM_setting_table *table, unsigned int count, unsigned char force_update)
  173. {
  174. unsigned int i;
  175. LCM_setting_table_V3 para_tbl[1];
  176. for(i = 0; i < count; i++) {
  177. unsigned cmd;
  178. cmd = table[i].cmd;
  179. switch (cmd) {
  180. case REGFLAG_DELAY :
  181. MDELAY(table[i].count);
  182. break;
  183. case REGFLAG_END_OF_TABLE :
  184. break;
  185. default:
  186. //dsi_set_cmdq_V2(cmd, table[i].count, table[i].para_list, force_update);
  187. para_tbl[0].cmd = table[i].cmd;
  188. para_tbl[0].count = table[i].count;
  189. if(para_tbl[0].count > 1){
  190. para_tbl[0].id = DSI_DCS_LONG_PACKET_ID;
  191. memcpy(para_tbl[0].para_list,table[i].para_list,para_tbl[0].count);
  192. }else if(para_tbl[0].count == 1){
  193. para_tbl[0].id = DSI_DCS_SHORT_PACKET_ID_1;
  194. memcpy(para_tbl[0].para_list,table[i].para_list,para_tbl[0].count);
  195. }else if(para_tbl[0].count == 0){
  196. para_tbl[0].id = DSI_DCS_SHORT_PACKET_ID_0;
  197. }
  198. dsi_set_cmdq_V3(para_tbl,1,1);
  199. }
  200. }
  201. }
  202. // ---------------------------------------------------------------------------
  203. // LCM Driver Implementations
  204. // ---------------------------------------------------------------------------
  205. static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)
  206. {
  207. memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS));
  208. }
  209. static void lcm_get_params(LCM_PARAMS *params)
  210. {
  211. memset(params, 0, sizeof(LCM_PARAMS));
  212. params->type = LCM_TYPE_DSI;
  213. params->width = FRAME_WIDTH;
  214. params->height = FRAME_HEIGHT;
  215. // enable tearing-free
  216. params->dbi.te_mode = LCM_DBI_TE_MODE_VSYNC_ONLY;
  217. params->dbi.te_edge_polarity = LCM_POLARITY_RISING;
  218. params->dbi.io_driving_current = LCM_DRIVING_CURRENT_6575_16MA;
  219. params->dbi.data_format.format = 3; // [chenlang], just a flag to idicate command set
  220. #if (LCM_DSI_CMD_MODE)
  221. params->dsi.mode = CMD_MODE;
  222. #else
  223. params->dsi.mode = SYNC_PULSE_VDO_MODE;
  224. #endif
  225. // DSI
  226. /* Command mode setting */
  227. params->dsi.LANE_NUM = LCM_TWO_LANE;
  228. //The following defined the fomat for data coming from LCD engine.
  229. params->dsi.data_format.color_order = LCM_COLOR_ORDER_RGB;
  230. params->dsi.data_format.trans_seq = LCM_DSI_TRANS_SEQ_MSB_FIRST;
  231. params->dsi.data_format.padding = LCM_DSI_PADDING_ON_LSB;
  232. params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888;
  233. // Highly depends on LCD driver capability.
  234. // Not support in MT6573
  235. params->dsi.packet_size=256;
  236. params->dsi.intermediat_buffer_num = 0;
  237. // Video mode setting
  238. //params->dsi.intermediat_buffer_num = 2;
  239. params->dsi.PS=LCM_PACKED_PS_24BIT_RGB888;
  240. #if 0
  241. params->dsi.vertical_sync_active = 4; //5;
  242. params->dsi.vertical_backporch = 6; //5;
  243. params->dsi.vertical_frontporch = 6; //5;
  244. params->dsi.vertical_active_line = FRAME_HEIGHT;
  245. params->dsi.horizontal_sync_active = 20;
  246. params->dsi.horizontal_backporch = 46;
  247. params->dsi.horizontal_frontporch = 21+10;
  248. params->dsi.horizontal_active_pixel = FRAME_WIDTH;
  249. #else
  250. params->dsi.vertical_sync_active = 4;
  251. params->dsi.vertical_backporch = 7;
  252. params->dsi.vertical_frontporch = 7;
  253. params->dsi.vertical_active_line = FRAME_HEIGHT;
  254. params->dsi.horizontal_sync_active = 78;
  255. params->dsi.horizontal_backporch = 78;
  256. params->dsi.horizontal_frontporch = 78;
  257. params->dsi.horizontal_active_pixel = FRAME_WIDTH;
  258. #endif
  259. // Bit rate calculation
  260. params->dsi.pll_div1=1; // div1=0,1,2,3;div1_real=1,2,4,4 ----0: 546Mbps 1:273Mbps
  261. params->dsi.pll_div2=1; // div2=0,1,2,3;div1_real=1,2,4,4
  262. params->dsi.fbk_div =33;//30; // fref=26MHz, fvco=fref*(fbk_div+1)*2/(div1_real*div2_real)
  263. }
  264. static void lcm_init(void)
  265. {
  266. #if defined(BUILD_LK)
  267. upmu_set_rg_vgp2_vosel(6);
  268. upmu_set_rg_vgp2_en(1);
  269. #else
  270. hwPowerOn(MT6323_POWER_LDO_VGP2, VOL_3000, "Lance_LCM");
  271. #endif
  272. MDELAY(20);
  273. SET_RESET_PIN(1);
  274. MDELAY(15);
  275. SET_RESET_PIN(0);
  276. MDELAY(5);
  277. SET_RESET_PIN(1);
  278. MDELAY(20);
  279. push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);
  280. }
  281. static void lcm_suspend(void)
  282. {
  283. #if 0
  284. push_table(lcm_deep_sleep_mode_in_setting, sizeof(lcm_deep_sleep_mode_in_setting) / sizeof(struct LCM_setting_table), 1);
  285. MDELAY(20);
  286. SET_RESET_PIN(1);
  287. MDELAY(15);
  288. SET_RESET_PIN(0);
  289. MDELAY(5);
  290. SET_RESET_PIN(1);
  291. MDELAY(20);
  292. #if defined(BUILD_LK)
  293. upmu_set_rg_vgp5_en(0);
  294. #else
  295. hwPowerDown(MT65XX_POWER_LDO_VGP5, "Lance_LCM");
  296. #endif
  297. #else
  298. SET_RESET_PIN(1);
  299. MDELAY(10);
  300. SET_RESET_PIN(0);
  301. MDELAY(10);
  302. SET_RESET_PIN(1); // fix me
  303. MDELAY(10);
  304. #endif
  305. }
  306. static void lcm_resume(void)
  307. {
  308. lcm_init();
  309. }
  310. static void lcm_update(unsigned int x, unsigned int y,
  311. unsigned int width, unsigned int height)
  312. {
  313. unsigned int x0 = x;
  314. unsigned int y0 = y;
  315. unsigned int x1 = x0 + width - 1;
  316. unsigned int y1 = y0 + height - 1;
  317. unsigned char x0_MSB = ((x0>>8)&0xFF);
  318. unsigned char x0_LSB = (x0&0xFF);
  319. unsigned char x1_MSB = ((x1>>8)&0xFF);
  320. unsigned char x1_LSB = (x1&0xFF);
  321. unsigned char y0_MSB = ((y0>>8)&0xFF);
  322. unsigned char y0_LSB = (y0&0xFF);
  323. unsigned char y1_MSB = ((y1>>8)&0xFF);
  324. unsigned char y1_LSB = (y1&0xFF);
  325. unsigned int data_array[16];
  326. data_array[0]= 0x00053902;
  327. data_array[1]= (x1_MSB<<24)|(x0_LSB<<16)|(x0_MSB<<8)|0x2a;
  328. data_array[2]= (x1_LSB);
  329. dsi_set_cmdq(data_array, 3, 1);
  330. data_array[0]= 0x00053902;
  331. data_array[1]= (y1_MSB<<24)|(y0_LSB<<16)|(y0_MSB<<8)|0x2b;
  332. data_array[2]= (y1_LSB);
  333. dsi_set_cmdq(data_array, 3, 1);
  334. data_array[0]= 0x00290508; //HW bug, so need send one HS packet
  335. dsi_set_cmdq(data_array, 1, 1);
  336. data_array[0]= 0x002c3909;
  337. dsi_set_cmdq(data_array, 1, 0);
  338. }
  339. static void lcm_setbacklight(unsigned int level)
  340. {
  341. unsigned int default_level = 145;
  342. unsigned int mapped_level = 0;
  343. //for LGE backlight IC mapping table
  344. if(level > 255)
  345. level = 255;
  346. if(level >0)
  347. mapped_level = default_level+(level)*(255-default_level)/(255);
  348. else
  349. mapped_level=0;
  350. // Refresh value of backlight level.
  351. lcm_backlight_level_setting[0].para_list[0] = mapped_level;
  352. push_table(lcm_backlight_level_setting, sizeof(lcm_backlight_level_setting) / sizeof(struct LCM_setting_table), 1);
  353. }
  354. static void lcm_setpwm(unsigned int divider)
  355. {
  356. // TBD
  357. }
  358. static unsigned int lcm_getpwm(unsigned int divider)
  359. {
  360. // ref freq = 15MHz, B0h setting 0x80, so 80.6% * freq is pwm_clk;
  361. // pwm_clk / 255 / 2(lcm_setpwm() 6th params) = pwm_duration = 23706
  362. unsigned int pwm_clk = 23706 / (1<<divider);
  363. return pwm_clk;
  364. }
  365. LCM_DRIVER RX_498HX_615B_82_lcm_drv =
  366. {
  367. .name = "RX_498HX_615B_82",
  368. .set_util_funcs = lcm_set_util_funcs,
  369. .get_params = lcm_get_params,
  370. .init = lcm_init,
  371. .suspend = lcm_suspend,
  372. .resume = lcm_resume,
  373. #if (LCM_DSI_CMD_MODE)
  374. .set_backlight = lcm_setbacklight,
  375. .update = lcm_update,
  376. #endif
  377. };